Socket receiving more than one message together

Asked

Viewed 202 times

0

I have a socket client receiving xml messages that is working normally but in some moments it is necessary that the server sends me more than one message related to a request, and these messages are sent in a very small time interval something like hundredths and then these messages come all together which makes the client’s interpretation difficult. Is it possible that the socket can receive these separate messages ? My socket is asynchronous.

private static void ReceiveCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the state object and the client socket 
                    // from the asynchronous state object.
                    StateObject state = (StateObject)ar.AsyncState;
                    Socket client = state.workSocket;

                    // Read data from the remote device.
                    int bytesRead = client.EndReceive(ar);

                    if (bytesRead > 0)
                    {
                        // There might be more data, so store the data received so far.
                        //state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                        String received = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
                        if (received == keepAliveMsg)
                        {
                            Console.WriteLine("[" + DateTime.Now.ToString() + "] - " + "Keep Alive received.");
                        }
                        else
                        {
                            sendToXMLController(received);
                            //Console.WriteLine("[" + DateTime.Now.ToString() + "] - " + received + "\n");
                        }



                            // Get the rest of the data.
                            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                                new AsyncCallback(ReceiveCallback), state);     


                    }                   

                    else {
                        // All the data has arrived; put it in response.
                        if (state.sb.Length > 1)
                        {
                            response = state.sb.ToString();
                        }
                        // Signal that all bytes have been received.
                        receiveDone.Set();
                    }



                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }

1 answer

0


No, there’s no way to get him to receive the messages separately.

To be more accurate, there is no separation of messages, or better yet, there are no "messages". These "messages" are an abstraction that is created in your program to work upon communication by the Sockets.

The guarantee you have when using TCP/IP is that the data will arrive and that they will arrive in the same order they were sent (just by comparison, UDP does not guarantee any of this). What he does not guarantee is that will arrive separately the data if were made consecutive submissions, in this case they can arrive together, and also that will arrive all at once, because another problem that you did not have but may come to have if the data is large is to get only part of the information, and then get separately the rest.

The communication should work in a loop more or less as follows

  1. Expects to arrive (more) data
  2. Receive the data and add it at the end of a received data buffer
  3. Checks if you already have enough data to handle in the buffer
    • If you already have enough data, remove the data from the beginning of the buffer and treat it as needed, then go back to (3), as it may be that more than one entire message has arrived together
    • If you do not have enough data back to the (1)

One detail is that the buffer I refer to is not the state.buffer of your code, this is the buffer that receives the communication bytes, what you need is another buffer to go saving all the incoming data.

In your code from to see that probably in the example you used they did this, this is seen by the commented line.

// There might be more data, so store the data received so far.
//state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

Then you should take what came in state.buffer and first of all add at the end of another buffer, as was being done with the state.sb, only after that you should check whether all the data has arrived.

And to know if all the data has arrived is another thing you will need to define in your program, creating a communication protocol of its own.

It can be quite simple, for example if you send only texts you can prefix the message with the size of it, to make it easier can be done with the hexadecimal value always with 8 digits, in the style

0000002C<meuxml><dados>Teste<dados></meuxml>

So I can read the first 8 characters and know that this message has 44 characters, 8 of which are prefix containing the size, so the loop would be like

  1. Expects to arrive (more) data
  2. Receive the data and add it at the end of a received data buffer
  3. Checks if you already have more than 8 characters in the buffer
    • If it has more than 8 characters you just read these 8 characters (without removing from the buffer) to find out the size of the message, otherwise it returns to (1)
    • Knowing the size of the message then you check if you have already received an equal or greater amount of characters, if yes, only then you remove this data from the beginning of the buffer, remove the prefix from it and treat them as needed, then go back to (3)because it may have arrived more than an entire message together, otherwise it goes back to the (1)

And this is just a very simple way of doing a text protocol, you could also use delimiters, but then you’d have to make sure that the delimiters would never show up in the text, and you’d have to look in the middle of the text for these delimiters, so I find the use of a prefix with the simplest size and practical, because you only need to read some characters at the beginning.

Browser other questions tagged

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