Socket receiving more than one message together

0

I have a client socket receiving messages in xml that is working normally but in some cases it is necessary for the server to send me more than one message regarding a request, and these messages are sent in a very small time interval something like hundredths and then these messages all come together which makes it difficult to interpret the client. Is it possible for the socket to 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());
                }
            }
    
asked by anonymous 08.01.2016 / 12:26

1 answer

0

No, you can not get the messages separately.

To be more correct, there is no separation of messages, or better still, there are no "messages". These "messages" are an abstraction that is created in your program to work on communication over 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 (only by comparison, UDP does not guarantee any of this). What he does not guarantee is that the data will arrive separately if consecutive submissions have been made, in this case they can arrive together, and also that it will arrive all at once, as another problem that you did not have but may have if the data is large is to get only part of the information, and then get separated the rest.

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

  • Expect to get (more) data
  • Receive data and add them to the end of a received data buffer
  • 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 return to (3), as more than one entire message may have arrived
    • If you do not have enough data back to (1)
  • A detail is that the buffer I am referring to is not the state.buffer of your code, this is the buffer that receives the bytes of the communication, what you need is another buffer to go saving all the data arriving.

    In your code 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 get what arrived at state.buffer and first of all add at the end of another buffer, as was done with state.sb , only after that is that you should check if all the data has already arrived.

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

    It can be very simple, for example if you only send texts you can prefix the message with the size of it, to be easier can be done with the value in hexadecimal 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 of the prefix containing the size, so the loop would be of type

  • Expect to get (more) data
  • Receive data and add them to the end of a received data buffer
  • Checks if you already have more than 8 characters in the buffer
    • If you have more than 8 characters you just read these 8 characters (without removing from the buffer) to find the message size, otherwise return to (1)
    • Knowing the size of the message then you check if you have received an equal or greater number of characters, if so, only then you remove this data from the beginning of the buffer, remove the prefix from it and treat them as needed, then back to (3), since it may be that more than one entire message has arrived together, otherwise it returns to (1)
  • And this is just a very simple way to do a text protocol, it would also be possible to use delimiters, but then you would have to make sure that the delimiters would never appear in the text, and you would have to look in the middle of the text delimiters, so I find the use of a prefix with the simplest and most practical size, since you only need to read some characters at the beginning.

        
    08.01.2016 / 13:27