我有一个用c ++编写的程序,可以在一个“镜头”中向闪存播放器发送一个23723字节的套接字。
Flash播放器有时会收到两个大小为17520和6203的数据包,有时会收到一个23723的数据包。
编辑:似乎没有办法获得与闪存发送数据相关的总字节数。这将使构建循环以重建“损坏的”数据包变得非常困难。
我认为TCP应该正确地重新组合数据包,我自己很难重新组合它们。
这是我在flash中的接收处理程序:
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 :(得分:2)
这与tcp无关。只要至少一个字节,套接字就可以向您发送任意数量的字节。所以你可能会得到[1,27322]。执行此操作的正确方法是在循环中调用read并自行填充数组。如果您的代码不包含循环但可以正常工作,则它会偶然起作用。没有循环就无法工作。
编辑:不要使用bytesAvailable。检查读取功能的返回值。检查你的代码:如果你的代码依赖于bytesAvailable那就错了。
Edit2:看起来像flash api(我不知道)与所有其他框架和语言使用的套接字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;
答案 1 :(得分:2)
好的......试着理解这一点。 TCP套接字不是通过网络传输数据包(至少在概念上),它实际上是一个字节流,它们以相同的顺序传输,以便在另一端接收,而不会失败。
现在较低层(IP等)将流分解为数据包并通过网络发送。接收端的TCP堆栈重新组装数据包(如有必要,请求重新传输),并在它不断接收来自较低层的数据包时再次形成流。目标上的read()
套接字调用将获取到目前为止在流中接收的字节。因此,您永远无法确定单个read()
来电是否会获取您发送的所有数据。
诀窍是使用多个read()
调用。您可以有两种可能的方案来处理这个问题:
(1)当你知道你应该接收多少字节时。在这里,您只需继续调用read()
,直到收到所述字节数。
(2)当你不知道你应该收到多少字节时。这很棘手。在这里你必须决定一个Sentinel。因此,在发送端,您发送所有必须发送的数据,然后发送此Sentinel。当我确定你必须明白它在接收端,你继续read()
直到你收到哨兵。
永远不要将TCP套接字视为数据包。当你把它们视为溪流时,它很容易陷入其中。