ofer alper
ofer alper

Reputation: 71

Strange/Severe Socket receive Bug in C#

I have a simple program that reads from the socket. Normally it works well. but sometimes The receive is reading 2 bytes that is already read. The structure of the message is 1 byte header, 3 bytes msgLength, msgLength bytes msg, byte trailer. I record the traffic with WireShark and it seems fine.

The problem occurs as follows:

packet X = ........ endOfPreviousMessage, trailer byte, header byte, first byte of msgLength
packet X+1 = 2 bytes the rest of the msgLength

It reads the msgLength correctly (the value is 253) The is read the 53 again! and the message. This, of course, are causing problem to the message parser.

the code:

Socket CAMListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
CAMListenSocket.Bind(new IPEndPoint(IPAddress.Any,CAMListenPort));
CAMListenSocket.Listen(10);

CAMSocket = CAMListenSocket.Accept();


    internal void CAMSocketReceive()
    {
        byte[] hdrBuffer = new byte[4];
        while (Active)
        {
            try
            {
                int read = CAMSocket.Receive(hdrBuffer,4,SocketFlags.None); //Reading the first 4 bytes
                if (read == 0)
                {
                    Logger.Warn(" disconnecting");
                    Active = false;
                    break;
                }
                int msgLength = Utils.BytesToInt(hdrBuffer, 1, 3); //Convert to int, skipping the first byte (which is the SOH)
                if (hdrBuffer[0] != 1)
                {
                    Logger.Warn("CAMSocketReceive::  Out of sync first byte is not SOH !! Handling recovery " );
                    //handleRecovery();
                }
                msgLength = msgLength + 1;//Add the trailer
                byte[] rawMsg = new byte[msgLength]; //Prepare a buffer to hold the CAM msg                                        
                read = 0;
                do
                {
                    read+= CAMSocket.Receive(rawMsg, read, msgLength - read, SocketFlags.None); //Read MSG_LENGTH bytes.                                                                        
                } while (read < msgLength);

                CAMMessage cam = new CAMMessage(rawMsg); //parse the message
                CAMQueue.Add(cam); //Add to the CAM queue
            }
            catch (Exception ex)
            {
                Logger.Error("Error while reading from CAM socket: ", ex);
            }
        }
    }

Upvotes: 0

Views: 469

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499900

Well, you've got one bug in your code here, to start with:

    int read = CAMSocket.Receive(hdrBuffer,4,SocketFlags.None);
    if (read == 0)
    {
        Logger.Warn(" disconnecting");
        Active = false;
        break;
    }
    int msgLength = Utils.BytesToInt(hdrBuffer, 1, 3);

What if read is 1, 2 or 3? You may not have read all 4 bytes. It's unlikely, but possible. If the message length is the same as for the previous message, you'd see exactly the behaviour you're describing. (It would probably be better to use a new byte array for each set of header bytes, then you wouldn't be reusing the "old" data, which could be causing confusion.)

I very much doubt that this is a bug in the .NET socket implementation.

For the sake of diagnostics, you could always log the return value of each call to Read, and possibly even the data that's been read.

Upvotes: 3

Related Questions