2012-01-17 53 views
0

我使用C來實現客戶端服務器應用程序。客戶端向服務器發送信息,服務器使用它發回信息。我目前正在編寫處理數據接收的代碼,以確保它實際上已經收到。C unix套接字編程讀取()問題

我遇到的問題表現出一些代碼後,最好的解釋:

int totalRead = 0; 
char *pos = pBuffer; 
while(totalRead < 6){ 
if(int byteCount = read(hSocket, pos, BUFFER_SIZE - (pos-pBuffer)>0)){ 
    printf("Read %d bytes from client\n", byteCount); 
    pos += byteCount; 
    totalRead += byteCount; 
    }else return -1; 
} 

上面的代碼運行在服務器端,將打印出「閱讀從客戶1個字節的」 6倍,並計劃將繼續正常工作。我在這裏硬編碼6,知道我正在從客戶端寫入6個字節,但我會讓我的協議要求發送的第一個字節是緩衝區其餘部分的長度。

int byteCount = read(hSocket, pBuffer, BUFFER_SIZE); 
printf("Read %d bytes from client", byteCount); 

上面的代碼,取代第一代碼段的使用,將打印「閱讀客戶端,從6個字節」,並繼續工作正常,但如果只有5人讀它並不能保證我收到的每個字節例如。

任何人都可以向我解釋爲什麼會發生這種情況和一個可能的解決方案?我猜第一種方法確保所有字節正在交付,但它看起來效率低下一次讀取一個字節...

哦,這是發生在一個分叉子進程,我使用tcp/ip。

注意:我的目標是成功實現第一個代碼段,以便確保我正在讀取所有字節,但我無法正確執行。

+0

您的協議還應該包含一些長度或內容分隔符,以便讓對方知道應該何時停止接收數據(類似於HTTP中的「Content-Length」或分塊編碼)。請參閱http://stackoverflow.com/a/6404085/372643 – Bruno 2012-01-17 15:08:17

回答

6

基本上這樣做的正確方法是你的兩個代碼片段的混合。做第一個,但不要一次只讀一個字節;請求你所期望的所有字節。但看看bytesRead,如果它比預期的要小,請調整目的地指針,調整預期的讀數,然後再次撥打read()。這就是它的工作原理:有時候你期望的數據會被分割成不同的數據包,並不是同時可用。

讀下面的評論,看看你的代碼,我很困惑,因爲是的,那就是你想要做的。但後來我看了密切你的代碼:

read(hSocket, pos, BUFFER_SIZE - (pos-pBuffer)>0)){ 
              ^
               | 
           THIS ---------| 

那「> 0」是封閉讀的論點,不是外面的括號;這意味着它是參數的一部分!事實上,你的最後一個參數被解釋爲

(BUFFER_SIZE - (pos-pBuffer)) > 0 

爲1,直到最後,當它變爲0

+0

是的!這就是我一直在嘗試做的事情,但問題是我無法弄清楚如何不一次只請求字節。我假設上面的第一個代碼段是要求所有的字節。在第一種情況下,如果我使用read(socket,pos,BUFFER_SIZE - (pos-pBuffer)),它不會嘗試讀取整個事情,因爲(pos-pBuffer)= 0,所以我的第三個參數是整個緩衝區大小? – pandaEater 2012-01-17 04:00:32

+0

看我的編輯。請不要傷害你的額頭撞在你的桌子上。 – 2012-01-17 04:08:20

+0

傷害......太浪費時間了。但非常感謝您的幫助! – pandaEater 2012-01-17 04:11:39

0

您的代碼是不完全正確。 readwrite可能不會讀取或寫入您請求的數據總量。相反,您應該在每次調用之後提前讀取或寫入指針,並計算您在傳輸中剩下的剩餘字節數。

如果您從readwrite中收回負值,則表示您收到錯誤消息。零表示傳輸已完成(沒有更多字節要發送),而任何大於零的數字表示在最後一次調用readwrite時發送的字節數。

+0

你能告訴我一些正確的代碼示例嗎?我的第一個代碼段試圖做你正在解釋的內容,但我無法正常工作。 – pandaEater 2012-01-17 04:09:19