.NET Async Server получает данные без видимой причины - PullRequest
0 голосов
/ 11 августа 2011

Я сейчас совершенно сбит с толку.

Редактировать: Хорошо, неважно. Сокет Python также начинает делать это сейчас.

Редактировать 2: Ну, не совсем уверен, что это вызывает высокую загрузку процессора, но что-то случайно. Есть ли эффективный способ выяснить, что вызывает скачки в использовании? Этот проект немного большой и имеет различные темы.

У меня есть асинхронный сервер, который прослушивает и ожидает входящие соединения, затем поддерживает их работу и ожидает сброса сокета и выдачи данных сервера. Он закрывается только тогда, когда пользователь хочет, чтобы сокет был закрыт.

Однако всякий раз, когда я позволяю сокету и потоку оставаться подключенным, он начинает терять скорость и начинает отправлять пустые данные по бесконечному циклу ... может пройти от 15 секунд до минуты, прежде чем он начнет выходить из строя. Если я позволю этому продолжаться действительно долгое время, это начнет вызывать очень высокую загрузку процессора.

Помимо высокой загрузки ЦП, как ни странно, все работает как надо; сообщения отправляются и принимаются в порядке.

Это моя функция обратного вызова для чтения:

    protected void ReadCallback(IAsyncResult ar)
    {
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.SocketHandle;

        try
        {
            int bytesRead = (state.BytesRead += handler.EndReceive(ar)), offset = 0;
            string line = m_Encoder.GetString(state.Buffer, 0, bytesRead);
            if ( state.Buddy != null )
                Console.WriteLine(state.Buddy.Address);
            if (bytesRead > 0)
            {
                Console.WriteLine("!!!");
                /* A complete request? */
                if (line.EndsWith("\n") || line.EndsWith("\x00"))
                {
                    string[] lines = line.Split('\n'); // ... *facepalm*
                    foreach (string ln in lines)
                        this.MessageReceieved(ln, state);

                    state.Buffer = new byte[StateObject.BUFFER_SIZE];
                    state.BytesRead = 0; // reset
                }
                /* Incomplete; resize the array to accommodate more data... */
                else
                {
                    offset = bytesRead;
                    Array.Resize<byte>(ref state.Buffer, bytesRead + StateObject.BUFFER_SIZE);
                }
            }
            if (handler != null && handler.Connected )
                handler.BeginReceive(state.Buffer, offset, state.Buffer.Length - offset, SocketFlags.None, new AsyncCallback(ReadCallback), state);

        }
        catch (SocketException)
        {
            if (state.Buddy != null)
                state.Buddy.Kill();
            else
                handler.Close();
        }
    }

Я знаю, что это как-то вызвано вызовом BeginReceive, но я не знаю, как еще поддерживать соединение.

1 Ответ

2 голосов
/ 11 августа 2011

В этом коде нет ничего, что могло бы сделать его бесполезным.

Хотя я вижу некоторые проблемы.

Обнаружение соединения

Нетнужно проверить, подключен ли сокет.Вы можете обнаружить разъединения двумя способами в обратном вызове приема:

  1. Нулевые байты возвращаются EndReceive
  2. Возникает исключение.

Я бы рекомендовал первым делом после EndReceive проверить возвращаемое значение и соответственно обработать отключение.Это делает код более понятным.

Ваш код в настоящее время ничего не сделает, если получено 0 байтов.handler просто прекратит прием и все равно будет считать, что соединение открыто.

Обработка буфера

Обработка вашего буфера очень неэффективна.Не изменяйте размер буфера каждый раз.Это сильно замедлит работу вашего сервера.Выделите большой буфер с самого начала.

Обработка строк

Не создавайте строки каждый раз, когда что-то получаете.Проверьте внутри байтового буфера после новой строки или вместо нуля.Затем создайте строку и сделайте ее настолько большой, насколько это необходимо.Вы можете получить больше байтов, чем просто сообщение (например, полтора сообщения)

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