TCPconnection: сервер не «понимает», что прием окончен - PullRequest
0 голосов
/ 10 января 2012

Я имею дело с проблемой соединения 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 ]

2 голосов
/ 10 января 2012

Если вы используете TCP, нет гарантии, что количество байтов, которое вы send на одной стороне, будет равно количеству, которое вы recv на другой стороне. Они могут быть разделены или объединены. Например, если вы отправили «ab», а затем «cd», вы можете получить «ab», затем «cd», или «a», затем «bcd», или «abcd», или «abc», затем «d», и т. Д. п.

Поскольку strstr прекращает поиск своего первого аргумента, когда он находит NUL-байт, и вы отправляете NUL-байты вместе с клиентом, вероятно, последний recv помещает что-то вроде "\ 0 \ 0 \ 0End" в ваш буфер, поэтому strstr считает его строкой нулевой длины и не находит подстроку "End".

1 голос
/ 10 января 2012

Вам нужно закрыть сокет отправки, когда вы закончите с ним.Пока вы не закроете (с close или shutdown) сокет, recv не вернет ноль.

0 голосов
/ 06 января 2014

ПРОБЛЕМА РЕШЕНА !!:

Я отправляю пакеты данных с таким количеством данных, как размер пакета! Раньше я отправлял, например, «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;
    }
...