Socket "cutting" bytes into two packets

Asked

Viewed 479 times

8

I am developing a Socket communication of my program with the server. This server is responsible for bridging between my program and the users that are connected to it, that is, the user when executing a change in the "program A", the user of the "program B" will receive this change and apply the changes automatically. The number of connected programs is undefined. Below is an example diagram:

Onde em vermelho é o envio de bytes e em azul é o recebimento.

Where in red is the sending of bytes and in blue is the receiving. The connection between the server and the client is unique and does not close. Where there are two receiving arrows in blue, it means the two changes sent in red.

Everything works correctly. The problem arose when I went to send a larger amount of bytes than I was testing and realized that the Socket object "chopped" the sending of bytes to the server, separating it into 2 packages, which, consequently, was received in two parts.

It turns out that these bytes are part of a single JSON object, and upon receiving the packages, the event ProgressEvent.SOCKET_DATA is dispatched twice, with the first and second part of the JSON object.

The sending code is:

function enviar(json:Object):void {
    var str:String = JSON.stringify(json); // transformo json em string
    socket.writeUTFBytes(str); // escrevo a string no objeto socket
    socket.flush(); // faço o envio
}

On receiving (This function runs 2 times, "cutting" bytes into two packets):

function receber(e:ProgressEvent.SOCKET_DATA):void {
    var str:String = socket.readUTFBytes(socket.bytesAvailable); // transformo os bytes em string
    var json:Object = JSON.parse(str);
}

Is there some kind of byte quantity submission limitation? Should I manage packet queues and sort by process? It happens in any language?

  • 3

    Dear biio, the limit of package size exists in any type of programming via Socket, what happens is that it is often done implicitly and is only noticed as in your case where the package arrives separately. I don’t know about actionscript to help you with this, but I do know that with C++ sockets you need to use the OS API to create the socket and also to change the size of the sent and received package. I hope someone can help you more specifically.

1 answer

11


The standard (and necessary!) procedure when programming in sockets is to repeat the reception until the expected number of bytes has been received.

How do you know the number of bytes to be received ? This is the responsibility of the application. A common method is to place a fixed header (header) at the beginning of each message, containing the size of the following message. The first step is the application to receive this fixed header. Even in this step it is necessary to eventually make repeated receptions. After receiving this fixed header, the application knows the size of the following message, and therefore makes repeated receptions until receiving the total bytes of the message.

The need for this procedure comes from the fact that the TCP protocol transmits and receives bytes, not messages. Thus, when an application sends 300 bytes there is no guarantee that on the other side this message will arrive in a single piece of 300 bytes. Theoretically, the message can reach 3 pieces of 100 bytes, for example, this is allowed by the TCP protocol. With small messages usually each send corresponds to a receive on the other side, but as the size of the messages increases the probability that they reach several pieces on the other side.

  • Thank you for the answer! I had already tried something similar, but I’ll try to explain it better: one of the problems I’ll probably face is when the application has more than one change being sent via Socket by the server. The server will be sending two parallel changes simultaneously to the application, divided into several packets with indefinite bytes. How can I put the header at the beginning of the changes and know that the packages with the remaining bytes are of the first or second change? The application would get lost, would not?

  • 1

    @biio If it is the same socket in TCP, they are not parallel, they are always sequential. If you are opening several connections, qq way tb will not mix the packages (and probably something is strange in the application, because usually the same channel is used for all communication). If you are going to use data interchange in a stream, it is still the responsibility of the application as it will mark each block. The important thing is that in TCP, if you send 5000 bytes and the load is divided into 3 parts, the 3 parts will arrive in the original sequence, so you don’t have much to worry about.

  • 2

    @your "task" is to read the data in a buffer. When you give the number of bytes of the header, take these bytes and consume in the application. Important: if you read the amount indicated in the header and left bytes, keep this leftover in buffer, as it is part of the next message that is coming.

  • @Bacco, I’m sorry to insist. I’m almost understanding or maybe it’s my explanations that are a little confused, rsrs. My client receives the server change data, and he is responsible for receiving the changes from other clients. These changes are sent by a single socket connection, ie on the same connection I may be receiving from the server (Receiving from other clients) n changes. If changes are sent in parallel, but queued, both byte packets are queued as well?

  • @Bacco, I made a change to the question with an image illustrating what I mean, rsrs.

  • 2

    @The change made does not change anything what was answered and what I said, that is simply what Joséx said. Anyway, for each client it will be a different connection, and on each connection, the bytes do not change order. This is one of the differences between TCP and UDP, for example. In TCP, what is sent, will be received in the same order. I just suggest taking care of the next questions you ask on the site to put all the details already in the beginning, because a substantial change can invalidate the answers already given. In the present case, it makes no difference, but it is good to avoid.

  • 2

    @biio Just an extra remark: don’t confuse the connection with the Istener. Normally a Switch can "listen" to multiple clients, but once started, each connection is independent.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.