Ton*_*ony 4 c++ udp protocol-buffers
我知道这可能很愚蠢,但我使用Google协议缓冲区定义的消息包并不能很好地与UDP一起使用UDP.当我通过UDP从客户端到服务器从序列化包(我只有一些普通字段)发送常规字符串时,每件事情都很好.但是当我添加一个重复的字段时,序列化的字符串只能被接收到整体的一部分.第一个字段将被完全接收,但所有其余字段将丢失.代码用c ++,Google协议缓冲区2.3.0,Linux编写.欢迎任何帮助.谢谢.
我的proto文件如下:
message Package{
optional string virtualPath = 1;
optional int32 num = 2;//0=insert, 1=find, 2=remove.
optional string realFullPath = 3;
optional bool isDir = 4;
repeated string listItem = 5;
optional int32 openMode = 6;
optional int32 mode = 7;
optional int32 Operation = 8;
optional int32 replicaNo =9;
}
Run Code Online (Sandbox Code Playgroud)
服务器端:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "zht_util.h"
int main(int argc, char *argv[]) {
struct sockaddr_in sad;
int port = 50000;
struct sockaddr_in cad;
int alen;
int serverSocket;
char clientSentence[1000];
char capitalizedSentence[1000];
char buff[1000];
int i, n;
serverSocket = socket(PF_INET, SOCK_DGRAM, 0); /* CREATE SOCKET */
if (serverSocket < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
memset((char *) &sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = INADDR_ANY;
sad.sin_port = htons((u_short) port);
if (bind(serverSocket, (struct sockaddr *) &sad, sizeof(sad)) < 0) {
fprintf(stderr, "bind failed\n");
exit(1);
}
while (1) {
clientSentence[0] = '\0';
alen = sizeof(struct sockaddr);
socklen_t len = (socklen_t) alen;
n = recvfrom(serverSocket, buff, sizeof(buff), 0,
(struct sockaddr *) &cad, &len);
strncat(clientSentence, buff, n);
printf("Server received :%s \n", clientSentence);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
客户端:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "zht_util.h"
int main(int argc, char *argv[])
{
struct sockaddr_in sad;
int clientSocket;
struct hostent *ptrh;
char *host;
int port;
char Sentence[1000];
char modifiedSentence[1000];
char buff[1000];
int n;
host = "localhost";
port = 50000;
clientSocket = socket(PF_INET, SOCK_DGRAM, 0);
if (clientSocket < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
memset((char *)&sad,0,sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_port = htons((u_short)port);
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL ) {
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
HostEntity destination;
destination.host = "localhost";
destination.port = 50000;
int current_sock = -1;
Package package;
package.set_virtualpath(randomString(25));
package.add_listitem("item--1");
package.add_listitem("item--2");
package.add_listitem("item--3");
package.add_listitem("item--4");
package.add_listitem("item--5");
package.set_realfullpath("Some-Real-longer-longer-and-longer-Paths");
cout << "package size: " << package.ByteSize() << endl;
char array[package.ByteSize()];
package.SerializeToArray(array, package.ByteSize());
strcpy(Sentence, array);
n=sendto(clientSocket, Sentence, strlen(Sentence)+1,0 ,
(struct sockaddr *) &sad, sizeof(struct sockaddr));
printf(" Client sent %d bytes to the server\n", n);
close(clientSocket);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于Jon提到的问题,我也试过这个,但仍然无效.
string Sentence = package.SerializeAsString();
n=sendto(clientSocket, Sentence.c_str(), (Sentence.size())+1,0 ,(struct sockaddr *) &sad, sizeof(struct sockaddr));
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 11
我怀疑这是问题所在:
strcpy(Sentence, array);
Run Code Online (Sandbox Code Playgroud)
你正在使用strcpy- 一旦它到达0字节就会停止,因为它将这个有点任意的二进制数据视为一个字符串.我怀疑你应该使用memcpy.
同样,以后不要使用strlen.避免将数据视为文本的所有函数.
(一般情况下,我要小心使用带有UDP的协议缓冲区,除非你有充分的理由相信每条消息都适合单个数据包,但这是另一回事.)
| 归档时间: |
|
| 查看次数: |
6209 次 |
| 最近记录: |