我知道这可能很愚蠢,但我用Google协议缓冲区定义的消息包不太适合使用UDP,而与TCP完美配合。 当我通过UDP从客户端向服务器发送序列化包中的常规字符串(其中我只有一些普通字段)时,每件事情都很好。但是当我添加一个重复字段时,序列化的字符串只能被接收到整体的一部分。第一个领域将被完全接收,但其余的将全部丢失。代码是用C++,Google协议缓冲区2.3.0,Linux编写的。 欢迎任何帮助。 谢谢。谷歌协议缓冲区不适用于UDP?
我的原文件如下:
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;
}
服务器端:
#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;
}
客户端:
#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;
}
对于乔恩提到的问题,我想这也仍然不起作用。
string Sentence = package.SerializeAsString();
n=sendto(clientSocket, Sentence.c_str(), (Sentence.size())+1,0 ,(struct sockaddr *) &sad, sizeof(struct sockaddr));
为什么不你使用TCP?什么是使用UDP的原因? (无论如何,大部分时间都用于传输,所以你应该使用TCP)。 –
你确定你的邮件完全符合128字节吗? – sarnold
有很多有效的理由使用UDP;例如,如果您正在流式传输实时视频或音频,并且不希望传输延迟并在每次数据包丢失时重新传输无用的过时数据,或者如果您要发送多播或广播数据,哪些TCP不支持。 –