Winsock send() блокирует сервер?

Я читал, что функция send() на Winsock блокируется до тех пор, пока не будет получен ACK от последнего пакета. Сейчас я играю с сервером для пошаговой ролевой игры. Все обрабатывается одним потоком (для 64 сокетов). Запрос получен, обработан и ответ записан в сокет(ы). Этот процесс нельзя прерывать.

Можно ли с помощью этого метода обработать, скажем, 1000 клиентов (один поток на каждые 64 сокета)?

Разве это не заблокирует весь сервер, если send() займет слишком много времени, или клиент злонамеренно не отправит ACK или соединение будет прервано?

Должен ли я разделить логику сети и обработки запросов на 2 потока? Если это так, поток, обрабатывающий сетевые передачи, все еще может быть заблокирован с помощью send() или recv().

Или было бы лучше использовать перекрывающийся ввод-вывод?


person Megatron    schedule 17.10.2012    source источник


Ответы (2)


send() блокируется, только если сокет работает в режиме блокировки, а исходящий буфер сокета заполняется данными из очереди. Если вы управляете несколькими сокетами в одном потоке, не используйте режим блокировки. Если один получатель не считывает данные своевременно, это может повлиять на все соединения в этом потоке. Вместо этого используйте неблокирующий режим, тогда send() сообщит, когда сокет перейдет в состояние, при котором произойдет блокировка, затем вы можете использовать select(), чтобы определить, когда сокет снова сможет принимать новые данные. Вместо этого лучше использовать перекрывающиеся порты ввода-вывода или порты завершения ввода-вывода. Отправьте исходящие данные в ОС и позвольте ОС обрабатывать все ваши ожидания, уведомляя вас, когда данные в конечном итоге будут приняты/отправлены. Не отправляйте новые данные для данного сокета, пока не получите это уведомление. Для масштабируемости до большого количества подключений порты завершения ввода-вывода, как правило, являются лучшим выбором.

person Remy Lebeau    schedule 17.10.2012
comment
Не могли бы вы объяснить, почему это будет отличаться, если используется несколько потоков? Сокеты распределяются по потокам, верно? - person Jori; 31.05.2014

Нет, это так не работает. Из документации MSDN на send:

Успешное завершение функции send не означает, что данные были успешно доставлены и получены получателю. Эта функция указывает только на то, что данные были успешно отправлены.

person Jonathon Reinhart    schedule 17.10.2012
comment
Более того, на самом деле это означает не то, что данные были успешно отправлены получателю, а то, что они были успешно поставлены в очередь в исходящем буфере сокета для последующей передачи получателю. . Если send() блокируется, это означает, что сокет работает в режиме блокировки, а очередь заполнена, ожидая, пока получатель прочитает и подтвердит некоторые данные, чтобы в очереди освободилось место. - person Remy Lebeau; 18.10.2012