Search code examples
c#socketstcpclient-serverpacket

C# Receiving Packet in System.Sockets with examples


in this qusetion C# Receiving Packet in System.Sockets a guy asked: "In my Client Server Application i wondered how to make a packet and send it to the server via the Client Then on the server i recognize which packet is this and send the proper replay"

and showed the example of his way of implementing the 'packet recognizer'. He got an answer that his way of 'structuring the message' is bad, but no explanation and code example followed by the answer.

So please, can anybody show the example of a good code, which should do something like this, but proper way:

[client]

Send(Encoding.ASCII.GetBytes("1001:UN=user123&PW=123456")) //1001 is the ID

[server]

private void OnReceivePacket(byte[] arg1, Wrapper Client)
{
    try
    {
        int ID;
        string V = Encoding.ASCII.GetString(arg1).Split(':')[0];
        int.TryParse(V, out ID);

        switch (ID)
        {
            case 1001://Login Packet
                AppendToRichEditControl("LOGIN PACKET RECEIVED");
                break;

            case 1002:
                //OTHER IDs
                break;

            default:
                break;
        }
    }
    catch { }         
}

Solution

  • TCP ensures that data arrives in the same order it was sent - but it doesn't have a concept of messages. For instance, say you send the following two fragments of data:

    1001:UN=user123&PW=123456
    999:UN=user456&PW=1234
    

    On the receiving end, you will read 1001:UN=user123&PW=123456999:UN=user456&PW=1234 and this might take one, two or more reads. This may even arrive in two packets as:

    1001:UN=user123&PW=12
    3456999:UN=user456&PW=1234
    

    This makes it very had to parse the message correctly. The other post mentions sending the length of a packet before the actual data, and that indeed solves the problem, as you can determine exactly when one message ends and the next starts.

    As an example, client and server could agree that each message starts with 4 bytes containing the length of the message. The receiver could then simply:

    • load 4 bytes exactly
    • convert to an integer, now you know the length of the remainder of the message
    • read exactly that many bytes and parse the message

    C# conveniently has the BitConverter class that allows you to convert the integer to a byte[] and vice versa.