2012-01-09 35 views
-1

我正在處理我正在建立的TCP連接的問題。當從客戶端向服務器發送數據時,服務器似乎「等待」另一個'recv()'(對我而言不那麼明顯),並且客戶端從不退出,因爲它已完成發送部分並等待'recv )'來自服務器的答案。這到了一種僵局。TCPconnection:服務器不'理解',接收結束

以下代碼是我認爲問題所在的部分。

Server代碼

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

}

正如你可以看到,我不介意發送DATAS但只有約包大小。 此代碼作品完美爲1包發送 ...但不是更多! :/ 如果發送的數據包多於要發送的數據包,則客戶端「阻塞」(需要^ C退出),服務器在循環開始時停止,在收到所有數據後循環!)。

我還有一個疑問,如果我使用'sizeof(BUFFSIZE)'而不是'BUFFSIZE',相同的確切代碼工作正常。我想知道爲什麼......:/任何想法?

例如./client:

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

./server:

的recv之前
接收358個字節
的recv後
之前的recv
接收676個字節
的recv後
BEF的recv/* stucks這裏*/

(...當我按下客戶CTR-C以下來... ...)
收到0字節
的recv後

收到的總字節數是1034/**接收的字節數量合適! **/

+0

你可以張貼更正的代碼摘錄作爲一個答案? – 2012-01-10 14:23:43

+0

在這裏你:) – FILIaS 2012-01-10 14:37:51

回答

-1

問題解決了!!:

我發送的數據包有這麼多的DATAS作爲數據包大小!之前,我以packet-size = 1024爲例說明了「abcde」。在客戶端使用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; 
    } 
+0

memset()與它有什麼關係? – EJP 2018-01-23 07:17:48

1

您需要在完成後關閉發送套接字。直到你關閉(與closeshutdown)套接字,recv不會返回零。

+0

我明白你的觀點,但那不是所有的代碼。 close()在我發佈的客戶端代碼的末尾。但即使這是真的,那麼爲什麼它會用於一個數據包發送? :/ – FILIaS 2012-01-09 20:56:29

+0

'send(sockfd,「End」,packet_size,0))!= packet_size)'應該是'send(sockfd,「End」,3,0))!= 3)',但那可能不是你看到的原因。你可以把所有的客戶端和服務器端編碼起來嗎? – 2012-01-09 21:02:34

+0

好吧,我說這是因爲我想要一個包的大小分佈。這不是一個概率,imo!你看到緩衝區有什麼問題嗎? – FILIaS 2012-01-09 21:04:41

2

如果您使用的是TCP,無法保證您在一側的send的字節數等於您在另一側的recv的數量。他們可能會分裂,或者連在一起。 例如,如果您發送了「ab」然後「cd」,您可以接收「ab」,然後「cd」或「a」,然後「bcd」或「abcd」或「abc」,然後「d」等等。

由於strstr停止搜索的第一個參數,當它找到一個NULL字節,並且你發送NUL與你的客戶字節,很可能最後recv是把像「\ 0 \ 0 \ 0End」在您的緩衝區,所以strstr認爲它是一個零長度的字符串,並沒有找到「結束」子字符串。

+0

好的提示!謝謝!但是你有什麼建議?我在最後沒有使用'bzero()'嘗試它,但它仍然無法正常工作。 – FILIaS 2012-01-09 21:50:29

+0

您可以創建一個像搜索內存的strstr函數。你必須傳遞緩衝區和目標序列的大小。但第二個想法,我不認爲這是解決方案。有一些我們沒有想到的細節。 – 2012-01-09 21:57:04

+0

是否有可能以不同的順序接收「結束」數據包的數據? (例如「nEd」)或者只是數據包的接收方式不同?我很好奇,如果有任何其他方式來解決它!即使不使用「結束」數據包! :/ – FILIaS 2012-01-09 22:07:28