Бизнес логика в порту завершения ввода / вывода

У меня есть некоторые сомнения в отношении порта завершения ввода-вывода, а также AcceptEx в winsock2

Пожалуйста, поправьте меня, если я ошибаюсь.

  1. AcceptEx — это перекрывающийся способ приема запросов или подключения. Однако, как указано в нескольких сообщениях на этом сайте, AcceptEx подвержен DOS-атаке, если AcceptEx ожидает данные, но не отправлен подключенным клиентом. Итак, можно ли это решить, просто поставив 0 на dwReceiveDataLength?

  2. Кроме того, каковы преимущества возможности получать данные от клиента при принятии соответствующего соединения, а не получать данные позже, используя AcceptEx?

  3. После принятия соединений от противоположной конечной точки и связывания его с портом завершения ввода / вывода запросы помещаются в очередь в порт завершения ввода / вывода как пакеты завершения, которые связаны с их соответствующим дескриптором. Рабочие потоки, которые блокируют порт завершения, будут разбужены в зависимости от NumberOfConcurrentThreads обслуживать запросы. Итак, есть ли потоки в порту завершения IO темы?

  4. Итак, где я должен реализовать бизнес-логику или работу на сервере сокетов? Например, запрос от клиента, который отправляет числа на сервер для обработки, в то время как сервер действует как калькулятор, который отвечает возвращением вычисленного результата. Таким образом, может ли эта логика быть реализована в порту завершения ввода-вывода?

  5. Если логика реализована в порту завершения ввода-вывода (когда IO темы (предполагается), которые активны в порту завершения ввода-вывода, выполняют WSARecv или же WSASend)), будет IO темы блокировать в ожидании завершения расчета, таким образом, не может быть принято соединение, если все резервы заняты?

Редакция:

  • Например, после принятия клиентского сокета и постановки в очередь / связанного в порту завершения ввода-вывода (main_cpl_port), темы, которые блокируют на этом main_cpl_port вызов GetQueuedCompletionStatus удалить пакет завершения из очереди и затем прочитать данные в выделенный буфер. Перед тем, как любой ответ будет записан обратно клиенту, буфер обрабатывается / анализируется для «команды» (например: GoToCalculator, GoToRecorder).
  • Например, GoToCalculator отвечает за другие команды, связанные с вычислениями.
  • В этом случае GoToCalculator фактически является еще одним портом завершения ввода-вывода, который обслуживает все эти запросы, связанные с вычислениями. Допустим, порт завершения называется как calc_completion_port.
  • Таким образом, возможно ли, что пакет завершения из main_cpl_port быть размещенным на calc_completion_port для будущего ввода-вывода (send и recv) из клиентского сокета, который в настоящее время связан с main_cpl_port. Это что PostQueuedCompletionStatus используется для?
  • Сообщение отправлено от клиента после публикации на calc_completion_port могут быть получены потоками, которые блокируют этот порт завершения?
    Другими словами, как я могу перенаправить соединение на другой порт завершения с другого?

1

Решение

1) Легко избежать потенциальной атаки AcceptEx DOS, просто не предоставляйте места для данных, и AcceptEx завершит работу, как только соединение будет установлено.

2) Использование AcceptEx означает, что вам не нужно иметь отдельный поток для запуска цикла принятия. Это удаляет один поток из вашей системы и уменьшает переключение контекста. Это особенно полезно, если вы прослушиваете несколько сокетов (разные порты / интерфейсы), так как каждый прослушивающий сокет должен иметь свой собственный принимающий поток.

3) Да, рабочие потоки, вызывающие GetQueuedCompletionStatus на IOCP, могут рассматриваться как потоки ввода-вывода …

4) Это зависит. Я построил системы с различными пулами потоков ввода-вывода фиксированного размера, которые никогда не выполняют никаких операций блокировки, и раздельными пулами потоков расширения, предназначенными для выполнения операций блокировки. Идея состоит в том, что это предотвратит блокировку всех потоков и предотвратит ввод / вывод … Это требует, чтобы вы передавали рабочие элементы другому пулу потоков, и это вызывает ненужное переключение контекста и сложность, но это означает, что у вас всегда есть потоки выполнять операции ввода-вывода (например, обрабатывать новые соединения после завершения AcceptEx) … Этот тип дизайна хорошо работал, когда API-интерфейсы IOCP использовались для отмены ожидающих операций, если поток, который был выпущен, завершился до завершения операции. Теперь, когда ОС изменила правила, и ожидающие операции не отменены, нет никакой реальной причины, по которой у вас нет просто расширяющегося / сжимающегося пула потоков ввода-вывода и выполняющих всю свою работу там … Вам просто нужно отследить, как доступно много потоков и создайте / уничтожьте потоки по мере необходимости, чтобы расширять / сокращать свой пул …

5) см. 4.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]