2013-10-09 53 views
0

我用tcp協議來處理客戶端的請求,發現一個現象,就是使用'send'函數時丟失了一些內容。代碼是作爲同胞:函數'send'的某些內容丟失

_stprintf(cData,"[%s]",send_back); 
    memset(send_back,0,sizeof(cData)); 
    int send_count; 
    if((send_count=send(service_sock,cData,_tcslen(cData),0))!=SOCKET_ERROR){ 
     fwrite(cData,sizeof(char),_tcslen(cData),hFile); 
     fflush(hFile); 
     g_log->print_log("%c%c%c%c",cData[0],cData[1],cData[2],cData[send_count-1]); 
     g_log->print_log("buffer len is :%d , send %d bytes",_tcslen(cData),send_count); 
     fclose(hFile); 
     memset(cData,0,sizeof(cData)); 
     return true; 
    } 

發送功能是總是成功的,和(CDATA)_tcslen的值等於send_count和CDATA [send_count-1]是 ']'。 但是,當我使用wireshark(捕獲工具)捕獲由套接字發出的數據包時,我發現一些內容總是丟失,包括']'的字符。內容由JSON協議封裝,所以']'是重要的。每次發送的總大小爲8900字節。但是,當我將請求項目一次(之前是100)更改爲50時,沒有任何遺漏,發回的大小約爲4000字節。 我不知道爲什麼會發生這種情況。

從我的日誌文件中,我確定名爲'cData'的數組包含全部內容,但爲什麼wireshark捕獲的數據包中的內容不完整?

+0

有沒有更晚的數據包包含其餘的數據? –

+0

剩餘的數據丟失,以後的數據包。 –

回答

0

看到您正在使用TCP,它已經看起來錯了。

首先,TCP是不適合一次性數據包(尤其是小型)的流協議,但其優點遠遠大於僅使用UDP代替。 請記住,如果TPC不在控制範圍內,則只能確保正確處理您的請求,實際的通信由Winsock庫完成。

永遠記住,發送功能LEN參數這是對你有多大的緩衝多少你可以發送一氣呵成,它可能會返回小於你想要發送提示的要求,這可能取決於很多因素髮生的頻率,讓我們說你使用回送設備,它可能永遠不會這樣做,這意味着發送將實際發送你所要求的。在一個真實的網絡中,它可能會以大約90%或更小的概率一次性發送。

你必須確保你發送儘可能多的,即檢查返回值和呼籲再發送,如果它沒有發送儘可能多的,並且做同樣的另一邊與recv ,請致電recv,直到您獲得儘可能多的數據爲止。如果您確切知道要通過網絡發送多少數據,此方法纔有效。對於丟失數據TCP來說,假設你檢查了send的返回值,我會說幾乎總是發送數據。如果存在網絡問題,比如丟失數據,您將看到TCP重傳數據包。

爲您發送的數據,這是更適合的方式,這是爲了確保你真的給你想要的數據量:

xint xsend(SOCKET s,const char* buf,xint len) 
{ 
xint lastSize; 
xint result; 

    if (len==0 || s==(SOCKET)NULL || buf==(const char*)NULL) 
     return SOCKET_ERROR; 

    lastSize=0; 
    result=0; 

    do 
    { 
     result=send(s,buf+lastSize,len-lastSize,0); 

     if (result==0) 
      return 0; 
     if (result==SOCKET_ERROR) 
      return SOCKET_ERROR; 
     if (result==len) 
      return len; 
     if (result>len) 
     { 
      xlog(1,"xsend : socket sent too much data [ %i of %i ]",result,len); 
      return SOCKET_ERROR; 
     } 
     lastSize+=result; 
     if (lastSize>len) 
     { 
      xlog(1,"xsend : socket sent too much data (overall) [ %i of %i ]",result,len); 
      return SOCKET_ERROR; 
     } 
     if (lastSize==len) 
      return len; 
    } 
    while (1); 

    xlog(2,"failed to do xsend"); 
    return SOCKET_ERROR; 
} 

這個代碼是剛剛從我的項目之一的複製粘貼, xlog是簡單的日誌記錄功能,你可以算出來。