2011-05-20 47 views
1

我有一個程序在c + +中發送一個23723字節的插口在一個「鏡頭」的Flash播放器。重新組合拆分TCP數據包與閃存套接字

Flash播放器有時接收大小17520和6203,其它時候的兩個分組接收23723.

EDIT的單個分組:似乎沒有成爲一個方式,以獲得相關聯的字節的總數與從閃光燈發送數據。這將使得構建重建「破損」分組的循環變得非常困難。

我認爲TCP應該正確地重新組合數據包,並且我自己很難重組它們。

這是我的閃光接收處理程序:

var socket:Socket = new Socket(); 
socket.addEventListener(Event.CONNECT, socketConnectHandler); 
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataReceivedHandler); 
socket.connect("127.0.0.1", 7445); 
socket.writeUTFBytes("hi"); 

private function socketDataReceivedHandler(event:ProgressEvent):void { 
    var socket:Socket = event.target as Socket; 
    trace(socket.bytesAvailable); 
    var data:ByteArray = new ByteArray(); 
    socket.readBytes(data); 
} 

命令:

trace(socket.bytesAvailable); 

將在次打印23723,並在其他時間,將打印17520緊接着6203總大小僅僅是示例,並且每個發送套接字都可能會發生更改。同時還可以發送或接收多個套接字,因此分組數據包可以相互混合。在C++中,我可以確定發送數據的總大小,即使我沒有收到全部發送的數據。

+0

否 - TCP不處理數據包。它只給你一個字節流。你應該首先寫入數據的大小,這樣你的閱讀結束就知道要讀取多少數據。或者,如果您始終發送固定數量的字節,請讓您的閱讀結束循環,直到閱讀全部內容。 – nos 2011-05-20 19:04:26

回答

2

這與tcp無關。只要至少有一個字節,套接字就可以發送任意數量的字節。所以你可能會得到[1,23722]。正確的做法是在循環中調用read並自己填充數組。如果你的代碼不包含循環,但可以工作,那麼它就是偶然的。沒有循環就無法工作。

編輯:不要使用bytesAvailable。檢查讀取函數的返回值。檢查你的代碼:如果你的代碼依賴於bytesAvailable,那就錯了。編輯2:看起來像flash api(我不知道)與所有其他框架和語言使用的socket api不同。我認爲它會工作相同,所以讓我糾正:你應該有以下循環:

int writePos = 0; 
var array = ...; 
while true: 
wait for bytes to become available. i do not know how to do this but one method would be 'while bytesAvailable == 0 then sleep 10' 
var bytesAvailableCopy = bytesAvailable; //copy because this value can change anytime 
socket.read(array, writePos, bytesAvailableCopy); 
writePos += bytesAvailableCopy; 
if(writePos == maxLength) break; 
+0

謝謝,但我該如何做循環?問題是在C++中,socket對象會告訴我應該得到多少字節。然後我可以循環,直到緩衝區等於我應該接收的字節數。但是,在Flash中,似乎沒有辦法獲得我應該得到的字節數。我認爲預期字節數的可用性是TCP的一部分。 – 2011-05-20 18:45:46

+0

添加代碼。注意,只有在所有字節都被消耗完後,循環纔會終止。它可以與任意數量的塊一起工作。 – usr 2011-05-20 18:51:50

+1

TCP套接字只是傳遞一個字節流。這取決於您的應用程序在頂部添加一個協議或層,將流分成有意義的數據包。 TCP確保數據按正確的順序到達。 – 2011-05-20 18:51:51

2

好吧...試着理解這一點。 TCP套接字不是通過網絡傳輸數據包(至少在概念上),它實際上是一個以相同順序傳輸並在另一端接收的字節流,而不會失敗。

現在,較低層(IP等)將流分解成數據包並通過網絡發送。接收端的TCP協議棧會重新組合這些數據包(如有必要,請求重新傳輸),並在其繼續接收來自較低層的數據包時再次形成一個流。在目的地上的一個read()套接字調用將獲取到目前爲止在流中接收到的字節。因此,您永遠無法確定一個單一的read()調用是否會將您發送的所有數據提取出來。

訣竅是使用多個read()調用。你可以有兩種可能的方案來解決這個問題:

(1)當你知道你應該接收多少個字節。在這裏,你只需要繼續撥打read(),直到收到上述字節數。

(2)當你不知道你應該接收多少字節。這相當棘手。在這裏你必須決定一個哨兵。所以,在發送端,你發送你必須發送的所有數據,然後發送這個Sentinel。當我確定你一定已經理解了,在接收端,你繼續read() ing,直到你收到哨兵。

永遠不要將TCP套接字視爲數據包。當你把它們想象成溪流時,它很容易沉入水中。