я должен использовать while (true) для получения данных от Socket? - PullRequest
8 голосов
/ 23 марта 2012

Пожалуйста, обратитесь к моему предыдущему вопросу для примера кода Сокеты: иногда (редко) пакеты теряются при получении

Мне нужно всегда получать данные из многоадресного сокета UDP.Это односторонняя передача, мне просто нужно прослушать новые данные и обработать их как можно скорее.

Должен ли я использовать while(true)?Мне не нравится while(true), потому что, на мой взгляд, это приводит к дополнительной нагрузке на процессор.Вероятно, C # предлагает другие методы обратного вызова или что-то?

Ответы [ 3 ]

4 голосов
/ 23 марта 2012

От 2 до 6 сокетов (комментарии), вероятно, в интересном месте, где либо блокировка, либо асинхронный ввод-вывод будут работать нормально, так как вы не забиваете машину потоками. С 2000 пакетов в секунду кажется, что есть много, чтобы держать потоки занятыми. Вам не нужно беспокоиться о while(true) с точки зрения производительности , поскольку метод Receive будет блокировать до тех пор, пока данные не станут доступными, поэтому никогда не выполняет горячую петлю ничего не делать. Тем не мение! Лично, с косметической точки зрения, я согласен, while(true) - ненужное пятно, поэтому, если вы используете блокирующий подход, возможно, подумайте:

int bytesRead;
while((bytesRead = socket.Receive(buffer)) > 0) {
    // process bytesRead from buffer
}

, который выйдет чисто, когда сокет закрыт.

Вы также можете сделать это с помощью либо методов BeginReceive и Socket.ReceiveAsync, которые не используют блокирующий вызов, но вместо этого используют либо событие, либо обратный вызов. Это особенно полезно при обработке большого количества соединений.

Лично , я обычно использую Socket.Available; если это положительно, то данные буферизуются и готовы к использованию, поэтому можно использовать простой Receive, чтобы получать эти данные быстро и без переключения контекста. Если он равен нулю, то данные в настоящее время не доступны , поэтому асинхронный вызов может быть более подходящим. Это уравновешивает переключение контекста с прямыми вызовами. Обратите внимание, что в подходе ReceiveAsync это также встроено через возвращаемое значение из ReceiveAsync (которое равно true, если операция не завершена, и обратный вызов будет вызван позже - и false, если операция уже завершено и нет обратного вызова будет вызвано).

1 голос
/ 23 марта 2012

Лучший способ программирования сокетов - использование их аналогов Async.Вместо запуска бесконечных циклов вы должны вызвать BeginReceive и установить его метод обратного вызова, который будет срабатывать после завершения передачи.Таким образом, вы сохраните контроль над своим приложением и будете использовать гораздо меньше ресурсов.

0 голосов
/ 23 марта 2012

Асинхронный метод является лучшим решением.

Однако в этом случае, если вы используете while (true), который содержит socket.Receive (buf), для процессора не требуется дополнительная работа, потому что если вы не установите тайм-аутsockect блокирует цикл до поступления данных.

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