2010-12-05 105 views
5

我已經試驗了兩個程序之間的異步TCP套接字消息,用於傳遞數據,數字和/或文本。我所做的是在每封郵件的開頭使用一個關鍵字,然後用「|」分隔這些值。字符。因此,一個消息可能是這樣的:如何分離TCP套接字消息

「數據| 490 | 40517.9328222222 | 1 | 6 | 11345 | 11347 | 11344 | 11345 | 106 | 40517.8494212963」

我設置讀取緩衝區大小爲1024,作爲最的消息將在這個長度內。但是有時我可能會發送很多短消息,其中幾個消息的長度小於1024個字符,看起來它會一次讀取。如果我發送超過1024個字符的消息,它將被拆分。所以我正在尋找一些關於如何處理這個問題的建議。我應該使用一些特殊字符來開始和/或結束每封郵件嗎?希望你對此有所建議。

回答

5

最簡單的方法是在每條消息的開頭髮送消息長度,這樣就可以在小端和大端硬件上運行。

這可以幫助您的接收器有效地預分配其接收緩衝區。

+0

謝謝!序列化意味着什麼?它適用於標準的Windows操作電腦嗎?有了你最後的評論,這是否意味着我應該根據收到的消息更改緩衝區大小?這將如何工作。由於消息的長度在消息已經被讀取之前是未知的,所以我不明白你的意思。順便說一句,是否有必要在發送方分解消息,還是不會影響性能?大小將是每200毫秒50個字符的消息,並且很少有50,000-400,000個字符的消息。 – bretddog 2010-12-06 11:27:59

+0

序列化僅意味着「以字符串形式輸出」。 @terminus的建議將是一種合理的方式 - 將消息長度轉換爲固定長度的字符串,以便在接收端輕鬆轉換回'unsigned int'。您可以請求先將這麼多字節讀入一個固定大小的緩衝區,然後分配一個緩衝區來接收剩餘的消息。不要在發送端分割消息 - TCP/IP堆棧將執行任何所需的分組。 – 2010-12-06 12:28:51

3

最簡單的方法是在數據包的開頭髮送消息的大小。這樣你就可以知道要讀取多少數據。所以它看起來像:

00015MESSAGE|1|2 ... 

大小字段有一個固定的大小是很重要的。

您也可以將此大小字段設置爲二進制,但您似乎正在發送純文本,因此您可以通過這種方式獲得可以人工讀取的大小字段。

0

您可以通過將唯一字節(如255不以ASCII顯示)填充到緩衝區大小並在接收端取消選中它們來解決該問題。 對我來說,這不是一個非常好的和聰明的解決方案,但它確實有效。

或者你也可以嘗試在每個包的開頭髮送整個數據包的長度,這是一個更加混亂的動作,並且當填充技術正確完成時更有效地工作。然後 合併包會是這個樣子(方案):

05|.....02|..03|... 
0

的方式TAR這麼做,是使用固定大小的塊。 TAR中的每個塊都是512字節,並且文件(消息)可能完全包含在該塊中。如果不是,則前512個字節包含一個標題,指定需要爲該文件(消息)讀取多少個附加塊。

Tar顯然不是TCP應用程序,但它具有類似的數據解析或處理要求。

此外,您的大小小於512字節,但也許它是有意義的,包括一個64字節的塊,或128或其他,並將所有的數據包裝在這種大小的包。你會因爲「盒子大小」的開銷而失去效率,但是你可能會獲得數據處理算法的效率和簡單性。

1

有幾種方法。

  1. 以每條消息爲前綴的長度字。

  2. 每個消息的STX/ETX樣式包裝,因此您可以看到它的起始位置和結束位置。這需要轉義出現在數據中的ETX字​​節,而這又需要轉義ESC字節。

  3. 自描述協議,例如XML或基於類型長度值的協議。

1

協議就是一切。對於我的聊天應用程序,我使用的參數協議,當您運行

shutdown.exe -s -f -t 30 

喜歡,但然後插槽我用這個

join John%20Doe   ' %20 for space 
msg This%20Is%20a%20test ' again %20 for space 

這樣,它並不重要,如果你的數據是發送異步:d希望這幫助