2013-01-07 43 views
2

我遇到了一些麻煩,從插座解析TCP包...解析TCP包

在我的方案,我的消息是這樣的:

「A''B」 'C''D''E' ......... 0x2300

'A''B''C''D''E' - >開始消息圖案

0x2300 - >兩個字節結束消息

但由於Nagle's algorithm,有時我的郵件被連接如下:

'A''B''C''D''E'......... 0x2300'A''B' 'C''D''E'......... 0x2300'A''B''C''D''E'......... 0x2300

我已經試圖setNoDelay()爲true,但問題仍然存在。

我有消息在一個字節[]。

我該如何拆分我的消息才能單獨解析?

PS:現在我能夠得到的第一個消息,但其他人都失去了......

+0

你的意思是把兩個消息放在一個字節數組中? –

+1

TCP是一個流,也無法保證讀取將給予相同長度的數據寫入數據,這是不是一個錯誤,你不能把它關掉。 –

+0

沒有TCP數據包這樣的東西。您正在解析在上次讀取中到達的流的不可預知且不可控制的位。這不是一回事,因爲沒有這種東西。 – EJP

回答

2

您必須將其視爲解析連續的字節流。您的代碼需要標識消息的開始和結束。

由於數據包發送的方式,您可能有完整的消息,多條消息,部分消息等等。您的代碼需要識別消息何時開始並持續讀取,直到它找到消息的結尾或者在某些情況下,當您讀取的字節數多於最大消息大小時,您需要重新同步。

我見過一些通訊管理員刪除並重新建立連接(重新開始),其他人丟棄數據,直到他們可以恢復同步。然後,您將開始瞭解您是否需要有保證的交付和轉播。

最好的協議是簡單的。創建一個消息頭,其中包含一個SOH字節,兩個字節的消息長度(或任何適當的),一個2字節的消息類型和1個字節的消息子類型。您還可以使用任意數量的字節結束消息。看一張ASCII圖表,有幾個十六進制字節00-1F,自從終端日以來相當標準。

這裏沒有重新發明輪子的意思。使它更容易,因爲你知道這個消息應該多長時間,而不是在數據中尋找模式。

+0

感謝您的解釋,但我仍然遇到一些與此相關的問題。我問了一個有關更多細節的新問題,我想如果你檢查它並給我一些消化。 http://stackoverflow.com/questions/14275242/tcp-socket-receiving-and-processing-multiple-messages/ – amp

3

只是遍歷你接收到的數據和檢查的最終標誌。當找到設置下一個包的開始索引並繼續搜索。事情是這樣的:

int packageStart = 0; 
for(int i = 0; i < data.length - 1; i++) { 
    if(data[i] == 0x23 && data[i + 1] == 0x00) { 
     // Found end of package 
     i++; 
     processPackage(data, packageStart, i); 
     packageStart = i; 
    } 
    // At this point: from packageStart till data.length are unprocessed bytes... 

如上所述,可能有一些遺留的數據(如果data沒有與結束標記結束)。您可能需要保留它,以便您可以將它預先添加到下一批接收的數據中。從而防止由於切斷TCP/IP包而造成的數據丟失。

+0

感謝您的解釋,但我仍然遇到與此相關的一些問題。我問了一個有關更多細節的新問題,我想如果你檢查它並給我一些消化。 http://stackoverflow.com/questions/14275242/tcp-socket-receiving-and-processing-multiple-messages/ – amp

-2

這聽起來像你需要把它當作字節流,並緩衝數據包,直到你看到你的EOF代碼0x2300。

+0

爲什麼?您可以逐字節地處理流。在處理任何事情之前,您當然不必緩衝整個事情。這在多請求/響應協議的情況下甚至不起作用。 – EJP

+0

他想要完整的信息,我仍然認爲各種「緩衝」是合理的解決方案。 (不是唯一的解決方案。)他從來沒有說過多重請求/響應是他TCP連接的一個例子。 – Alex