2012-02-26 177 views
1

我正在開發一個客戶端 - 服務器項目,並且需要實現一個邏輯,我需要通過TCP套接字連接檢查是否收到最後一個數據,然後才能繼續。 爲了確保我收到了所有的數據,我計劃在發送的最後一個數據包中加上一個標誌。我在下面有兩個選項,還有相關的概率。通過TCP填充數據

i。如下所示使用一個結構體,併爲最後發送的數據包填充vst_pad,並在recv端檢查它是否存在。在方案二的優勢在於,我沒有刪除從實際數據中的標誌將其寫入到file.Just之前檢查結構

typedef struct 
    { 
    /* String holding padding for last packet when socket is changed */ 
    char vst_pad[10]; 
    /* Pointer to data being transmitted */ 
    char *vst_data; 
    //unsigned char vst_data[1]; 
    } st_packetData; 

問題是我必須序列的結構上的第一個成員每次發送呼叫。此外,我不確定是否會在一次recv調用中通過TCP接收整個結構,因此每次都必須添加邏輯/開銷以檢查它。到目前爲止,我已經實現了這一點,但後來發現基於流的TCP可能無法保證在一次調用中收回整個結構體。

ii。使用像strncat這樣的函數將該標誌添加到最後發送的數據。

問題是我必須檢查每個接收調用或者使用正則表達式函數或像strstr函數那樣的標誌的存在,如果必須從數據中刪除它。

此應用程序將用於大數據傳輸,因此希望在每次發送/接收/讀取/寫入呼叫時增加最小開銷。真的很感激知道是否有更好的選擇,然後上述兩個或任何其他選項來檢查收到的最後一個數據包。該程序是多線程的。

編輯:我不知道我要發送的文件的總大小,但我發送的是固定數量的數據。這是fgets讀取,直到大小指定爲-1或直到遇到新行。

回答

2

您是否事先知道數據的大小,是否需要實現消息標誌的結束?

因爲我會簡化設計,所以添加一個4字節的標題(假設您不會發送每條消息超過4GB的數據),其中包含消息的預期大小。

因此,您解析出前4個字節,計算大小,然後繼續調用recv,直到獲得大量數據。

您需要處理recv調用從下一條消息中獲取數據的情況,以及顯然的錯誤處理。

如果實際消息包含10個零字節,則會發生如下問題:10字節小鍵盤解決方案沒有提出什麼問題 - 假設您用零填充它?你需要避開10字節的零,否則你可能會錯誤地截斷消息。

使用固定大小的標題和已知大小的值將緩解此問題。

+0

Alan:我不知道我要發送的文件的總大小,但是我發送的是固定數量的數據。也就是說,fgets會讀取,直到大小指定爲-1或直到遇到新行。我可以在緩衝區上使用strlen來查找實際的數據長度。 – user369823 2012-02-27 01:16:24

+1

,當然你必須解析這4個字節,這些字節可能會在4個不同的recv呼叫中到達。 – bew 2012-02-27 16:08:12

+0

@Alan:Thnx爲答覆到目前爲止。我部分實現了你的建議,但我想知道我到底知道了些什麼大小要放在標題中。我正在使用fgets讀取文件中的數據,並傳輸相同數量的大小。但是作爲它的TCP,我不確定發送數據的大小,直到檢查發送呼叫的返回值爲止。我有點困惑於此。一個僞代碼將是非常有用的... – user369823 2012-06-03 03:10:00

0

您可以使用用C#編寫的開源網絡通信庫嗎?如果是這樣結賬networkComms.net

+0

問題標記爲C,它是一個低級別的TCP消息應用程序。 – Alan 2012-02-26 19:02:34

+0

MarcF:謝謝你的回覆。正如Alan所指出的那樣,我再次在C.Thnks編碼。 – user369823 2012-02-27 02:07:08

1

對於一條消息(數據包)首先發送一個短的(按網絡順序)的大小,然後是數據。這可以在一個write系統調用中實現。

在接收端,只需read短期和轉換回主機順序(這將使一個在稍後的狀態下使用不同的處理器。然後,您可以read數據的其餘部分。

+0

埃德:感謝您的答覆。我已經發送了固定數量的數據,但不確定從文件中獲取的數據是否具有相同的大小或小於它的大小。 fgets和send函數在其調用中具有相同數量的len。你是否建議使用像strlen這樣的函數來找出要分配給短變量的實際數據長度? – user369823 2012-02-27 02:04:36

0

如果這是真正地由你的應用程序發送的最後一個數據在發送端使用shutdown(socket, SHUT_WR);

這將設置TCP標誌,它表示發送者 - 接收者流已經結束,接收者將知道這是因爲他的recv()在接收到所有內容時將返回0(就像EOF條件),接收器仍然可以發送數據,發送者可以ñ仍然聽他們,但它不能發送更多使用此連接。

+0

BatchyX。按照設計我以後會需要相同的連接。我不知道稍後會不會使用相同的連接。這取決於用戶的選擇。 – user369823 2012-02-27 02:05:52

1

在這種情況下,通常會將數據分塊爲塊,並提供塊頭和尾部。標題包含塊中數據的長度,所以對等方知道預期的時間 ​​- 只需要計算rx個字節,然後檢查一個有效的預告片。該塊允許在兩端沒有大量緩衝區的情況下進行大量數據傳輸。

在頭文件中添加一個可以識別最後一個塊的「狀態」字節並不麻煩。

另一種方法是打開另一個數據連接,對整個序列化進行流式處理,然後關閉這個數據連接(就像FTP一樣)。

+0

Martin:感謝您的及時答覆。我可以根據Ed先生在結構中所建議的添加空格來指示數據的長度,然後在recv端循環,直到收到數據量。我會嘗試首先執行相同的操作。 – user369823 2012-02-27 02:00:44