TCP连接:服务器不“理解”接收结束

时间:2012-01-09 20:45:53

标签: c sockets serversocket recv

我正在处理我正在构建的tcp连接上的问题。当从客户端向服务器发送数据时,服务器似乎“等待”(对我而言不那么明显)另一个'recv()'并且客户端永远不会退出,因为它已完成发送部分并等待'recv( )'来自服务器的答案。这陷入了一种僵局。

以下代码是我认为存在问题的部分。

服务器代码

  #define BUFFSIZE 1024;
  char buffer[BUFFSIZE];
  /*...*/
  bzero(buffer,BUFFSIZE);
  while(received > 0) {     /* indicates end of connection */   

      /* recv: Check for more data coming from client*/
          printf("before recv\n");
      if( (received = recv(sock,buffer,BUFFSIZE-1,0) ) < 0){
        perror("Failed to recv bytes from client");
        exit(1);
      } 
      printf("received %d bytes \n", received); 
      sum_bytes += received;

      printf("after recv\n");
      if( strstr(buffer,"End")) {
        printf("strstr: %s\n",buffer);
        break;
      }               
      bzero(buffer,BUFFSIZE);
}
printf("\ntotal bytes received are %d \n", sum_bytes);

客户代码

for(i=0; i<num_packets; i++){          

          /* Send the packet to the server */
          char packet[packet_size];
          bzero(packet,packet_size);
          if( (sent = send(sockfd,packet,packet_size,0)) != packet_size){
              perror("Client: send() sent a diff num of bytes than expected");
              exit(1);
          }       
          bytes += sent;
    }
    /* send another final packet("End")in order to inform server that sending is over */
    if( (sent = send(sockfd,"End",3, 0)) != 3) {
          perror("Client:send() sent a diff num of bytes than expected");
    }
    bytes += sent;
    printf("total bytes sent are %d \n", bytes);

}

正如您所看到的,我不介意发送数据,而只考虑数据包大小。 此代码可以完美 1个数据包发送 ...但不是更多! :/ 如果有多个数据包而不是一个要发送的数据包,那么客户端“阻塞”(需要^ C退出)并且服务器在接收到所有数据之后在循环开始时停止(他再做一次循环!)

我的另一个查询是,如果我使用'sizeof(BUFFSIZE)'而不是'BUFFSIZE',相同的确切代码可以正常工作。我想知道为什么......:/任何想法?

例如./client:

END
total bytes sent are 1034 
/* press ^C */

./服务器:

  在recv之前

  收到358字节
  在recv之后   在recv之前   收到676字节
   在recv之后   bef recv / *卡在这里* /

     

(...当我在客户端按ctr-c时会出现以下情况...)
  收到0个字节
  在recv之后

     

收到的总字节数是1034 / **正确的字节数量! ** /

3 个答案:

答案 0 :(得分:2)

如果您使用的是TCP,则无法保证一侧send的字节数与另一侧的recv相等。它们可以分开,也可以连在一起。 例如,如果您发送“ab”然后“cd”,您可以收到“ab”然后“cd”,或“a”然后“bcd”,或“abcd”,或“abc”然后“d”,等等类推。

由于strstr在找到NUL字节时停止搜索其第一个参数,并且您正在向客户端发送NUL字节,因此最后recv可能会出现类似“\ 0 \ 0”的内容\ 0End“在你的缓冲区中,所以strstr认为它是一个零长度的字符串,并没有找到”结束“子字符串。

答案 1 :(得分:1)

完成后,您需要关闭发送套接字。在您关闭(使用closeshutdown)套接字之前,recv不会返回零。

答案 2 :(得分:-1)

问题已解决!!:

我发送的数据包的数据量与数据包大小一样多!在此之前,我发送了例如“abcde”,其数据包大小= 1024。在客户端使用memset,问题解决了! 谢谢你的帮助!

正确的代码(仅在客户端更改):

for(i=0; i<num_packets; i++){          
          /* Send the packet to the server */
          char packet[packet_size];
          memset(packet,'-',packet_size);
          if( (sent = send(sockfd,packet,packet_size,0)) != packet_size){
              perror("Client: send() sent a different number of bytes than expected");
              exit(1);
          }       
          bytes += sent;
    }