Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
仅发送一条消息时从receive获取两条消息_C_Sockets_Networking - Fatal编程技术网

仅发送一条消息时从receive获取两条消息

仅发送一条消息时从receive获取两条消息,c,sockets,networking,C,Sockets,Networking,我编写了一个服务器,在打开与客户端的连接后,它应该等待来自客户端的消息: while(1){ if(recv(mySocket, buffer, 1000, 0) < 1){ continue; } printf("Message received: %s", buffer); } while(1){ if(recv(mySocket,buffer,1000,0)因此recv也返回两次,但是客户端只发送一个packet将recv的返回值保存在一个变量中,并每次

我编写了一个服务器,在打开与客户端的连接后,它应该等待来自客户端的消息:

while(1){
  if(recv(mySocket, buffer, 1000, 0) < 1){
     continue;
  }   
  printf("Message received: %s", buffer);
}
while(1){
if(recv(mySocket,buffer,1000,0)<1){
继续;
}   
printf(“收到的消息:%s”,缓冲区);
}
我向wireshark检查了哪些数据包被发送到此服务器,但对于每个发送的数据包,都有2个printf输出

我现在的问题是,我从哪里得到这个额外的信息


(附加的消息是一些随机字节。但每次都是一样的。)

您对
recv()
行为的明显期望是没有道理的。正如@KarolyHorvath在评论中所观察到的,流套接字(其中包括基于TCP的套接字)对“消息”没有任何意义。特别是,网络数据包不对应于流套接字上的消息。POSIX对
recv()
的行为有这样的描述,事实上:

对于基于流的套接字,[…]消息边界应被忽略

虽然这更有可能产生组合多个“消息”的效果,但也可能意味着单个消息(由单个
send()
调用发送)被拆分为多个
recv()
调用。当然,意味着如果指定给
recv()
的缓冲区长度小于套接字上实际接收的字节数,但也有其他情况可以获得该结果


成功时,
recv()
返回复制到接收缓冲区的字节数。如果您真的试图实现某种“消息”交换,那么您可以使用它来帮助您在消息边界上分割传入数据。但是,请务必认识到,这构成了在流的顶部实现消息传递协议,因此发送方和接收方需要进行合作(至少是隐式合作),以使其正常工作。

John Bollinger的回答是准确的,并为您提供了创建可靠的客户机/服务器应用程序应采取的措施的见解

关于您的问题,还有一个问题可以解释您看到的实际输出。正如您使用wireshark观察到的那样,数据包很可能在单个数据块中发送和接收。错误在您的服务器中:您接收字符数组中的数据,并使用
printf
将其直接打印为字符串。我怀疑数据包不包含终止的
“\0”
,从而使缓冲区成为
“%s”
的正确字符串
printf
将输出数据包内容加上缓冲区中的任何内容,直到到达
'\0'
字节,可能会调用未定义的行为。如果数据包被分成几个块,您可能会多次看到相同的内容,并且还会看到随机字符

以下是您应该如何修复代码:

char buffer[2000];
...
for (;;) {
    ssize_t count = recv(mySocket, buffer, 1999, 0);

    if (count >= 1) {
        buffer[count] = '\0';
        printf("Message received: |%s|", buffer);
    }
}
请注意,缓冲区必须至少比最大数据包大小长1字节,并且此跟踪方法无法处理数据包中嵌入的
'\0'
字节


当然,数据包可以在客户端和服务器之间进行切片和分块,因此您必须适当地处理此问题以实现适当的协议。

您收到了两个数据包吗?@Ed Heal Well printf被称为两次->因此recv也返回两次,但是客户端只发送一个packet将recv的返回值保存在一个变量中,并每次打印它。如果为零,则您没有收到消息,因此不应打印缓冲区。@jarmod I将If(recv(mySocket,buffer,1000,0)=-1)更改为If(recv(mySocket,buffer,1000,0)<1),但没有任何更改。这是什么类型的套接字?数据包的长度是多少?我想还有更多,你的答案几乎肯定是不完整的,但我正在等待OP的回应……你是对的。数据包被拆分,因为接收缓冲区的大小只有几个字节。@scaletos,我很高兴你发现了这个问题。但是,我重申,通过TCP连接的数据包数量及其有效负载的大小在很大程度上是
recv()
附带的。您可能会发现,接收到足够大的缓冲区通常允许您逐个数据包读取数据包,但您不能依靠通过
send()
发送的“消息”与数据包以1:1的比例对应,也不能依靠通过这种连接接收的数据包与
recv()接收的“消息”以1:1的比例对应
。谢谢,但我的服务器只用于打印小于1000字节(包括空字节)的邮件。@scaleos:是否将
'\0'
字节作为数据包的一部分传输?