2014-02-12 165 views
1

我正在編程TCP服務器客戶端。我分別使用單獨的send系統調用發送三個字符串。 但接收端我只獲得單個字符串,這是我發送的第一個字符串。剩下的兩條字符串錯過TCP客戶端未能發送字符串到服務器

下面我給出了我的服務器客戶端程序的一部分。

client.c

char *info = "infolog"; 
char *size = "filesize"; 
char *end = "fileend"; 
send(client, info, strlen(info)+1, 0); 
send(client, size, strlen(size)+1, 0); 
send(client, end, strlen(end)+1, 0); 

server.c

while ((read_size = recv(client, msg, sizeof(msg), 0))) { 
    printf("Data: %s\n", msg); 
    memset(msg, 0, sizeof(msg)); 
} 

實際輸出:

Data: infolog 

預期輸出

Data: infolog 
Data: filesize 
Data: fileend 

謝謝。

+0

試着打印'read_size'。您很可能同時收到了三條消息。 – mpontillo

+0

@Mike你說得對。我收到所有字符串的strlen。爲什麼服務器不能單獨收到? – sujin

+0

請參閱下面的Basile的答案。 TCP是基於流的,因此根據網絡條件,緩衝等,您可能會收到比已發送更多的輸出,或更少的輸出。 – mpontillo

回答

3

嘗試打印出read_size。您可能已收到所有消息。

由於Nagle's Algorithm,發件人可能會批量調用您的三個send()調用併發送一個數據包到服務器。雖然你可以禁用Nagle的算法,但在這種情況下,我認爲這不是一個好主意。你的服務器需要能夠處理部分數據的接收,並且處理接收比預期更多的數據。

您可能需要考慮使用上層協議來處理消息,如Google Protocol Buffers。看看techniques頁面,他們在這裏描述他們如何做它:建立一個協議緩衝區,並在寫入緩衝區之前將其長度寫入流。這樣接收端可以讀取長度,然後確定需要讀取多少字節才能獲得完整的消息。

+0

是否有任何可能的方法來實現我需要?我已經實現了TCP中的大部分代碼。所以改變協議不可能。 – sujin

+2

@sujin:不,不是。您必須設計協議和應用程序來管理字節流,TCP中沒有「應用程序消息」的概念。你的代碼應該承擔這一點。 –

+2

實際上,如果你不處理這個問題,你沒有正確地實現你的代碼:你犯了一個巨大的設計錯誤。 –

3

TCP不是消息協議,而是字節流協議。

三個send -s可以recv -ed作爲一個單一的輸入(或別的東西,例如兩個或五個recv等....)

應用程序應該分析輸入和緩衝它是能夠將其拼接成有意義的消息。

傳輸可以拆分或合併消息,例如,中間路由器可以並將分裂或合併「數據包」。

在實踐中,您最好有一些關於您的消息的良好慣例。要麼決定每條消息是例如換行符被終止,或者決定它以某個頭部的大小開始。

HTTPSMTPIMAPSCGIONC/XDR或(在RFC5531記錄)作爲具體例子。並且記錄你的協議(最低限度,對一些家庭作業玩具項目的長篇描述性評論,更嚴格的是在單獨的公開文件中)。

相關問題