Странно / Суровое Сокет получает ошибку в C # - PullRequest
0 голосов
/ 29 декабря 2010

У меня есть простая программа, которая читает из сокета. Обычно это работает хорошо. но иногда прием читает 2 байта, которые уже прочитаны. Структура сообщения 1 байтовый заголовок, 3 байта msgLength, msgLength байты msg, трейлер байтов. Я записываю трафик с помощью WireShark, и он кажется нормальным.

Проблема возникает следующим образом:

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

Он правильно читает msgLength (значение 253). Снова читается 53! и сообщение. Это, конечно, вызывает проблемы с анализатором сообщений.

код:

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);
            }
        }
    }

1 Ответ

3 голосов
/ 29 декабря 2010

Ну, у вас есть одна ошибка в вашем коде, для начала:

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

Что если read равно 1, 2 или 3?Возможно, вы не прочитали все 4 байта.Это маловероятно, но возможно.Если длина сообщения такая же, как и в предыдущем сообщении, вы увидите точно поведение, которое вы описываете.(Возможно, было бы лучше использовать новый байтовый массив для каждого набора байтов заголовка, тогда вы не будете повторно использовать «старые» данные, что может вызвать путаницу.)

I очень Сильно сомневаюсь, что это ошибка в реализации сокета .NET.

Ради диагностики вы всегда можете записать возвращаемое значение каждого вызова в Read и, возможно, даже данные, которыебыло прочитано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...