-2

I'm dealing with a problem on the tcp connection I'm building. When, sending datas from client to server, the server seems to "wait"(not so obvious to me why) for another 'recv()' and the client never exits, as it has finished the sending part and waits to 'recv()' an answer from the server. That comes to a kind of deadlock.

The following code is the part where,I think,the problem is.

Server code:

  #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);

Client Code:

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);

}

As you can observe, I don't mind about the sending datas but only about the packet sizes. This code works perfect for 1 packet sending... but not for more! :/ if there are more packets than one to be sent, then the client "blocks" (needs ^C to exit) and the server stops on the beginning of the loop, after he has received all the datas (he does one more loop!).

One more query that I have is that the same exact code works fine if I use 'sizeof(BUFFSIZE)' instead of 'BUFFSIZE'. And I am wondering why... :/ Any ideas?

e.g ./client:

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

./server:

before recv
received 358 bytes
after recv
before recv
received 676 bytes
after recv
bef recv /* stucks here*/

(...the following comes when i press ctr-c on client...)
received 0 bytes
after recv

total bytes received are 1034 /** right amount of bytes received!! **/

Aziz Shaikh
  • 16,245
  • 11
  • 62
  • 79
FILIaS
  • 495
  • 4
  • 13
  • 26

3 Answers3

2

If you're using TCP, there's no guarantee that the number of bytes you send on one side will equal the amount you recv on the other side. They could be split up, or joined together. For example, if you sent "ab" and then "cd" you could receive "ab" then "cd", or "a" then "bcd", or "abcd", or "abc" then "d", and so forth.

Since strstr stops searching its first argument when it finds a NUL byte, and you're sending NUL bytes with your client, it's likely the last recv is putting something like "\0\0\0End" in your buffer, so strstr considers it a zero-length string and doesn't find the "End" substring.

Samuel Edwin Ward
  • 6,526
  • 3
  • 34
  • 62
  • Nice Tip! Thanks! But what do you suggest? I tried it without 'bzero()' at the end...but it still doesn't work properly. – FILIaS Jan 09 '12 at 21:50
  • You could create a function like strstr that searches memory. You'd have to pass the size of the buffer and target sequence in. But on second thought, I don't think this is the solution either. There's some detail we're not thinking of. – Samuel Edwin Ward Jan 09 '12 at 21:57
  • Is there a chance that even the datas of "End" packet will be received in different order? (eg. "nEd") Or just the packets are being received differently? I am curious if there is any alternative way to solve it! Even without using "End" packet! :/ – FILIaS Jan 09 '12 at 22:07
  • No, TCP [guarantees](http://tools.ietf.org/html/rfc793#section-1.5) that each byte will be received in order, without any missing or duplicate bytes, or it is an error. I don't think you need the "End" packet at all personally; when `recv` returns zero, the client has finished. – Samuel Edwin Ward Jan 10 '12 at 14:18
  • I tried it without the "End" packet...and again it blocks! Don't know why either. – FILIaS Jan 10 '12 at 14:39
1

You need to close the sending socket when you are done with it. Until you close (with close or shutdown) the socket, recv will not return zero.

Samuel Edwin Ward
  • 6,526
  • 3
  • 34
  • 62
  • I see your point,but that's not the all code. close() is on the end of the client's code I posted. But even if that was true, why would then it works for one packet sending? :/ – FILIaS Jan 09 '12 at 20:56
  • `send(sockfd,"End",packet_size, 0)) != packet_size)` should probably be `send(sockfd,"End",3, 0)) != 3)`, but that's probably not the cause of what you're seeing. Could you put all of the client and server cod e up? – Samuel Edwin Ward Jan 09 '12 at 21:02
  • well,I put that 'cause I want a certain packet's size distribution. That's not a prob,imo! Do you see anything wrong with the buffer? – FILIaS Jan 09 '12 at 21:04
-1

PROBLEM SOLVED!!:

I send data packets with so many datas as the packet-size! Before, I sended for example "abcde" with packet-size=1024. With using memset in the client, problem solved! Thanks for helping!

Correct code (altered only in client):

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;
    }
FILIaS
  • 495
  • 4
  • 13
  • 26