Как устроено iocp в System.Net.Socket?

305
30 августа 2017, 13:13

Как IOCP устроено в нативе - понятно. Создается IO порт, к нему привязываются сокеты. Запускается несколько потоков с GetQueuedCompletionStatus, которые и обрабатывают пакеты. Отправляются запросы с сокетов на подключения к серверам.

1) Но как это реализовано в дотнете? Ведь мы не видим никакого аналога GetQueuedCompletionStatus или чего то подобного. Мы не видим самого IO порта. Мы работаем с асинхронными сокетами - как с синхронными. Вообще сколько портов IO используются на какое колл-во сокетов? Всего один или несколько? Сколько потоков обрабатывают пакеты с помощью GetQueuedCompletionStatus?

2) Что конкретно делает опция Socket.UseOnlyOverlappedIO? Написано только, что она принуждает сокет работать только в IO режиме. Но тогда резонный вопрос, какой режим сокета используется если не выставить эту опцию? Синхронный? Неблокируемый? RIO (хотя о чем я говорю, рио еще не допилили)...

p.s. извините за такое колл-во вопросов, но информации по этому аспекту действительно почти нету.

Answer 1

В пуле потоков есть отдельный поток, который занимается ожиданием на IOCP.

Когда вы вызываете BeginReceive, он начинает с подготовки структуры OverlappedAsyncResult путем вызова его метода SetUnmanagedStructures. На этом этапе .NET Framework определяет какой метод будет использоваться для получения результата - IOCP (начиная с WinNT) или обычный асинхронный вызов (Win9x). Непосредственный выбор способа происходит в базовом классе BaseOverlappedAsyncResult.cs в строке 158.

Если система решила использовать IOCP - у сокета вызывается метод BindToCompletionPort. В новых фреймворках он вызывает внешний метод ThreadPool.BindHandle(m_Handle);, реализация которого выложена в общий доступ только для coreclr, подробности можно видеть в файле win32threadpool.cpp.

Но есть и .NET-реализация через P/Invoke, которая сейчас отключена директивами условной компиляции. Ее можно увидеть на referencesource в классе SocketThreadPool.

Начинать изучать ее можно с функции ThreadPoolFunc(). Как видно из нее, в пуле потоков существует один или несколько IO-потоков, ждущих на общем для всех сокетов IOCP и вызывающих колбеки.

READ ALSO
Извлечь данные пользователя

Извлечь данные пользователя

Создаю программу "Банкомат"Возник вопрос - как сделать чтобы пользователь ввел свой ид, и сразу показало его счет и фио класс банкомат

317
Запретить повторное открытие tabPage c#

Запретить повторное открытие tabPage c#

Здравствуйте, подскажите пожалуйста, как запретить повторное открытие страницы tabPage1, через buttonТ

271