1
votes

I have a program in c++ that sends a socket of 23723 bytes to a flash player in one "shot".

The flash player sometimes receives two packets of size 17520 and 6203, and other times it receives a single packet of 23723.

EDIT: There does not seem to be a way to obtain the total number of bytes associated with the send data from flash. This would make it very difficult to build a loop to reconstruct the "broken" packet.

I thought TCP was supposed to correctly recombine the packets and I am having difficulty recombining them myself.

This is my receiving handler in 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);
}

The command:

trace(socket.bytesAvailable);

will at times print 23723, and at other times, will print 17520 quickly followed by 6203. The total size are just examples and are subject to change for each send sockets. Also many sockets can be sent or received at the same time, so the split packets can be inter-mixed. In c++ I could determine what the total size of the sent data was, even if I did not receive the whole sent data yet.

2
No - TCP does not deal with packets. It gives you just a stream of bytes. You should e.g. write the size of the data first, so your reading end knows how much data to read. Or if you always send a fixed number of bytes, have your reading end loop until it read all of them.nos

2 Answers

2
votes

This has nothing to do with tcp. The socket can send you any number of bytes as long as it is at least one byte. So you might get [1, 23722]. The correct way to do this is to call read in a loop and fill an array yourself. If your code does not contain a loop but works, then it works by accident. This cannot work without a loop.

Edit: do not use bytesAvailable. Check the return value of the read function. Check your code: If your code relies on bytesAvailable it is wrong.

Edit2: Looks like the flash api (which I do not know) works differently from the socket api that all other frameworks and languages use. I assumed it would work the same, so let me correct: You are supposed to have the following loop:

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;
2
votes

Okay... try and understand this. TCP Sockets isn't about transferring packets over the network (at least conceptually), its actually a stream of bytes which are transferred in the same sequence to be received on the other end, without fail.

Now the lower layers (IP and so on), breaks the stream into packets and send it over the network. The TCP stack on the receiving end reassembles the packets (ask for retransmissions if necessary) and form a stream out of it again, as and when it keeps receiving the packets from lower layers. A read() socket call on the destination will fetch you the bytes that are received in the stream so far. Therefore, you can never be sure if a single read() call will fetch you all the data that was sent.

The trick is to use multiple read() calls. You can have two possible scenarios to deal with this:

(1) When you know how exactly many bytes you're supposed to receive. Here, you just keep on calling read() until you have received the said amount of bytes.

(2) When you don't know how many bytes you're supposed to receive. This is rather tricky. Here you have to decide on a Sentinel. So, at the sending end, you send all the data that you have to send and then send this Sentinel. By the time I'm sure you must have understood it that at the receiving end, you keep on read()ing until you receive the Sentinel.

Never think of TCP-Sockets as packets. Its easy to sink it in when you think of them as streams.