我正在使用winsock用c ++编写一个小型客户端/服务器应用程序,我无法解释正在发生的一些事情。 我写了两个基本函数,通过TCP连接发送/接收所有数据..
bool sending(SOCKET source, char* buff, int size, int flags = 0)
{
int sent = 0;
int totalst = 0;
int total = size;
while(totalst != total)
{
sent = send(source, buff+totalst, size-totalst, flags);
if(sent > 0)
{
totalst += sent;
}
if(sent == SOCKET_ERROR)
{
return false;
}
}
return true;
}
bool receive(SOCKET source, char* buff, int size, int flags = 0)
{
int rec = 0;
int totalrc = 0;
int total = size;
while(totalrc != total)
{
rec = recv(source, buff+totalrc, size-totalrc, flags);
if(rec > 0)
{
totalrc += rec;
}
if(rec == SOCKET_ERROR)
{
return false;
}
}
return true;
}
服务器发出一个整数,其中包含将跟随它的数据块的大小。在我的情况下,这个数据块的大小不应该改变,它应该总是92600字节,但有时客户端会收到92604而是字节。奇怪的是,如果我在发送块大小和块本身(使用Sleep)之后让服务器等待,它总是会发送我期望的内容。
int i=0;
while(i < 100)
{
i++;
dat = getData();
len = sizeof(dat);
sending(source, (char*)&len, sizeof(len));
sending(source, dat, len);
Sleep(200);
}
由于滞后,客户端是否会收到不正确的字节值? 有没有办法解决这个问题? 任何帮助表示赞赏!
答案 0 :(得分:2)
考虑这个例子:
char *x = "!";
send(socket, x, 1); // destination, buffer, size
send(socket, x, 1);
send(socket, x, 1);
send(socket, x, 1);
你期望在这里发生什么?
char buffer[4];
recv(socket, buffer, 4); // source, buffer, size
实际上,四个send
发送的数据可以收到一个recv
。您无法保证,如果您对n
进行send
来电,则会n
拨打recv
来接收所有数据。
正如nos所评论的那样,TCP没有实现消息边界。这是你的工作,在应用层。 Winsock不会发送额外的数据。
答案 1 :(得分:0)
您的发送和接收功能都存在错误。
您正确地跟踪发送/接收的总字节数,以便您可以退出循环,但是在后续的send / recv调用中忘记调整“buff”和“size”的值。如果要发送的缓冲区必须通过多次调用发送,您将发送错误的数据。
同样,如果需要多次调用“recv”,您将覆盖在缓冲区开头复制的数据。
应该是:
sent = send(source, buff+totalst, size-totalst, 0);
同样对于recv案例:
rec = recv(source, buff + totalrc, size-totalrc, 0);
我不确定这是否会导致您的问题,但我有一种感觉,当todda指出的情况为真时,您的数据流会因此错误而被破坏。
有意义吗?此外,您应该准备好处理recv()将返回0的情况。
我希望这会有所帮助。