У меня есть некоторые сомнения в отношении порта завершения ввода-вывода, а также AcceptEx в winsock2
Пожалуйста, поправьте меня, если я ошибаюсь.
AcceptEx — это перекрывающийся способ приема запросов или подключения. Однако, как указано в нескольких сообщениях на этом сайте, AcceptEx
подвержен DOS-атаке, если AcceptEx ожидает данные, но не отправлен подключенным клиентом. Итак, можно ли это решить, просто поставив 0 на dwReceiveDataLength
?
Кроме того, каковы преимущества возможности получать данные от клиента при принятии соответствующего соединения, а не получать данные позже, используя AcceptEx
?
После принятия соединений от противоположной конечной точки и связывания его с портом завершения ввода / вывода запросы помещаются в очередь в порт завершения ввода / вывода как пакеты завершения, которые связаны с их соответствующим дескриптором. Рабочие потоки, которые блокируют порт завершения, будут разбужены в зависимости от NumberOfConcurrentThreads
обслуживать запросы. Итак, есть ли потоки в порту завершения IO темы?
Итак, где я должен реализовать бизнес-логику или работу на сервере сокетов? Например, запрос от клиента, который отправляет числа на сервер для обработки, в то время как сервер действует как калькулятор, который отвечает возвращением вычисленного результата. Таким образом, может ли эта логика быть реализована в порту завершения ввода-вывода?
Если логика реализована в порту завершения ввода-вывода (когда IO темы (предполагается), которые активны в порту завершения ввода-вывода, выполняют WSARecv
или же WSASend
)), будет IO темы блокировать в ожидании завершения расчета, таким образом, не может быть принято соединение, если все резервы заняты?
Редакция:
GetQueuedCompletionStatus
удалить пакет завершения из очереди и затем прочитать данные в выделенный буфер. Перед тем, как любой ответ будет записан обратно клиенту, буфер обрабатывается / анализируется для «команды» (например: GoToCalculator, GoToRecorder).PostQueuedCompletionStatus
используется для?1) Легко избежать потенциальной атаки AcceptEx DOS, просто не предоставляйте места для данных, и AcceptEx завершит работу, как только соединение будет установлено.
2) Использование AcceptEx означает, что вам не нужно иметь отдельный поток для запуска цикла принятия. Это удаляет один поток из вашей системы и уменьшает переключение контекста. Это особенно полезно, если вы прослушиваете несколько сокетов (разные порты / интерфейсы), так как каждый прослушивающий сокет должен иметь свой собственный принимающий поток.
3) Да, рабочие потоки, вызывающие GetQueuedCompletionStatus на IOCP, могут рассматриваться как потоки ввода-вывода …
4) Это зависит. Я построил системы с различными пулами потоков ввода-вывода фиксированного размера, которые никогда не выполняют никаких операций блокировки, и раздельными пулами потоков расширения, предназначенными для выполнения операций блокировки. Идея состоит в том, что это предотвратит блокировку всех потоков и предотвратит ввод / вывод … Это требует, чтобы вы передавали рабочие элементы другому пулу потоков, и это вызывает ненужное переключение контекста и сложность, но это означает, что у вас всегда есть потоки выполнять операции ввода-вывода (например, обрабатывать новые соединения после завершения AcceptEx) … Этот тип дизайна хорошо работал, когда API-интерфейсы IOCP использовались для отмены ожидающих операций, если поток, который был выпущен, завершился до завершения операции. Теперь, когда ОС изменила правила, и ожидающие операции не отменены, нет никакой реальной причины, по которой у вас нет просто расширяющегося / сжимающегося пула потоков ввода-вывода и выполняющих всю свою работу там … Вам просто нужно отследить, как доступно много потоков и создайте / уничтожьте потоки по мере необходимости, чтобы расширять / сокращать свой пул …
5) см. 4.
Других решений пока нет …