Re[9]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.11.07 19:20
Оценка:
Здравствуйте, k732, Вы писали:

Pzz>>Ну вот и возьми Tap-Win32. На первые полгода-год этого хватит.


K>вопрос стоит 2-3 недели. Все готово кроме этого. Если получиться общаться с ситемой, то остальное дело техники — приложения на более высоком уровне. (DHCP, DNS, WEB...)


Ну отлично — прикрутите пока Tap-Win32, это можно сделать за пару дней. Потом разберетесь. Все равно, после того, как проект будет полностью свинчен, какое-то время уйдет на доводку.

А что за проект-то такой забавный?
Re[5]: имитация сетевого интерфейса
От: k732  
Дата: 08.11.07 19:21
Оценка:
Pzz>WinPCap позволяет 1) послать пакет через такой-то сетевой интерфейс 2) принять пакеты, пришедшие на такой-то сетевой интерфейс (все или с фильтром, фильтр достаточно быстрый). Это не то же самое, что добавить в систему сетевой интерфейс.

Pzz>WinPCap тоже приносит с собой NDIS'овский драйвер, только не минипорт, а протокол. Если сравнивать с Tap-Win32, трудно сказать, кто из них хуже


Блин — везде засада
Re[10]: имитация сетевого интерфейса
От: k732  
Дата: 08.11.07 19:27
Оценка:
Pzz>А что за проект-то такой забавный?

Имитация сетевого интерфейса — виртуальные службы
Re[11]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.11.07 19:28
Оценка:
Здравствуйте, k732, Вы писали:

Pzz>>А что за проект-то такой забавный?


K>Имитация сетевого интерфейса — виртуальные службы


А можно чуть подробнее? Любопытно мне очень...
Re[12]: имитация сетевого интерфейса
От: k732  
Дата: 08.11.07 19:30
Оценка:
Pzz>А можно чуть подробнее? Любопытно мне очень...

ответ на ответ

P.S. Неужели кроме как полностью поднять драйвер нельзя дотянуться до ndis ?
Re[13]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.11.07 19:33
Оценка:
Здравствуйте, k732, Вы писали:

Pzz>>А можно чуть подробнее? Любопытно мне очень...


K>ответ на ответ


K>P.S. Неужели кроме как полностью поднять драйвер нельзя дотянуться до ndis ?


Никак. NDIS живет в ядре, чтобы общаться с ним, нужен драйвер. Если бы было решение попроще, я бы сразу присоветовал бы именно его...
Re[14]: имитация сетевого интерфейса
От: k732  
Дата: 08.11.07 19:36
Оценка:
Pzz>Никак. NDIS живет в ядре, чтобы общаться с ним, нужен драйвер. Если бы было решение попроще, я бы сразу присоветовал бы именно его...
Блин... Я надеялся что можно...

Ответ. Нужно создать что-то вроде WmWare. Приходят пакеты и нужно перенаправлять их системе.
Re[15]: имитация сетевого интерфейса
От: Аноним  
Дата: 08.11.07 23:07
Оценка:
Здравствуйте, k732, Вы писали:

K>Ответ. Нужно создать что-то вроде WmWare. Приходят пакеты и нужно перенаправлять их системе.


Тогда начните с виртуального минипорта из DDK.
Пакеты на виртуальный адаптер из вашей программы "приходить" будут? Это не так трудно сделать.
Re[16]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.11.07 23:19
Оценка:
Здравствуйте, Аноним, Вы писали:

K>>Ответ. Нужно создать что-то вроде WmWare. Приходят пакеты и нужно перенаправлять их системе.


А>Тогда начните с виртуального минипорта из DDK.

А>Пакеты на виртуальный адаптер из вашей программы "приходить" будут? Это не так трудно сделать.

Вот уж чего бы я точно врагу не пожелал, так это начинать с DDK'ных самплов, и потом править их по месту напильником.

DDK'ные самплы надо рассматривать только в качестве иллюстрации к DDK'ной документации. С целью уточнения, правильно ли мы поняли описание той или иной функции. Код у большинства из них очень плохо структурирован, и каждое действие, которое по-хорошему надо бы делать в каком-то одном месте, размазано тонким слоем по всему исходнику. Хороший пример того, как не надо писать код на Си (чтобы плюсятники не смеялись).

Поддерживать потом такой код, выпилиный напильником из DDK'ного сампла — проще пойти и удавиться.

Я это однажды пробовал на драйвере размером в 45 тышш строк (поддерживать, написали его не мы, хотя половина этого драйвера была спортирована с моего линуксячего драйвера для той же железки) — воспоминания остались на всю жизнь
Re[17]: имитация сетевого интерфейса
От: Аноним  
Дата: 09.11.07 12:21
Оценка:
Предлагаете к примеру фильтр файловой системы или редиректор с нуля писать?
Встречаются конечно в DDK samples те еще поделки, но основная часть примеров написана так, как надо. Да, бывает что не хватает структурированности, но не нужна в примере на 30 кб какая-то особенная структурированность — за лесом всяких шаблонов проектирования можно легко упустить детали, которые этот пример должен был продемонстрировать.
Кстати насчет деталей — вы конечно можете самостоятельно написать NDIS miniport или Ndis interm. driver, но с первого раза обязательно упустите пару тонких моментов; позже вы узнаете о них, когда клиенты пришлют дампы
Более того, основные примеры из DDK просто расчитаны на то, что их будут использовать в качестве заготовок и пишут эти примеры далеко не рядовые программисты, а люди проектировавшие части ядра.

Драйвер для железяки в 45 т строк — видеокарточка или сетевая карта? Наверное, дело там не в MS, а в кривых руках тех, кто это писал

Посмотрел драйвер из OpenVPN, наверное в данном случае будет проще его использовать, там уже приделано взаимодействие с приложением, не знаю правда, что с производительносьтью.
Re[18]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 09.11.07 13:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Предлагаете к примеру фильтр файловой системы или редиректор с нуля писать?


Вот именно фильтр файловой системы я предлагаю писать руками профессионала — того, кто не боится писать код.

Кстати, я слышал, там давно уже появились минифильтры, и это дело перестало быть такой уж ракетной наукой.

А>Встречаются конечно в DDK samples те еще поделки, но основная часть примеров написана так, как надо. Да, бывает что не хватает структурированности, но не нужна в примере на 30 кб какая-то особенная структурированность — за лесом всяких шаблонов проектирования можно легко упустить детали, которые этот пример должен был продемонстрировать.


Когда за паттернами приектирования теряется смысл, это называется overdesing. Большинство DDK'ных самплов грешат отсутствием дизайна, как такового. Кроме того, в них встречаются откровенные ошибки, причем как раз в тех местах, использование которых эти самплы как раз и должны демонстрировать.

Да Вы посмотрите, как в этих самплах та же синхронизация сделана. В одном файле захватываем spin lock, в другом отпускаем, в 3-м делаем что-то волшебное с атомарным счетчиком, имеющее отношение к той же синхронизации. И там оно все такое. И чего это демонстрирует? Как не надо писать программы на Си? Ну так я про это и говорю, не надо брать оттуда код. Берите оттуда только знания.

А>Кстати насчет деталей — вы конечно можете самостоятельно написать NDIS miniport или Ndis interm. driver, но с первого раза обязательно упустите пару тонких моментов; позже вы узнаете о них, когда клиенты пришлют дампы


Пиля сампл напильником, вы упустите ровно те же тонкие моменты. Только получив дампы, будет гораздо труднее разобраться, к чему они относятся.

А>Более того, основные примеры из DDK просто расчитаны на то, что их будут использовать в качестве заготовок и пишут эти примеры далеко не рядовые программисты, а люди проектировавшие части ядра.


По-моему, это легенда. Мне очень трудно себе представить, чтобы у ключевого разработчика нашлось время на написание сампла. Ну разве что где-нибудь на отпуске, наспор, что он сможет написать живой драйвер после 3-х кружек пива

А>Драйвер для железяки в 45 т строк — видеокарточка или сетевая карта? Наверное, дело там не в MS, а в кривых руках тех, кто это писал


WiFi. Драйвер обычной сетевой карты редко разрастается до таких масштабов.

Между прочим, один из DDK'ный самплов написан теми же сами кривыми руками, которые переносили мой линуксячий драйвер в венду. Поубивал бы!
К сожалению, профессиональная этика не позволяет назвать мне фамилию гада.

Блин, мы угробили 1.5 человекогода на поддержку этого драйвера в более-менее живом состоянии (а для начала просто починили грубые ошибки — такие, как блокировка на NDIS_EVENT'е на DISPATCH_LEVEL'е). А потом, когда настал удобный в политическом плане момент, за 3 месяца переписали его нахрен.

А>Посмотрел драйвер из OpenVPN, наверное в данном случае будет проще его использовать, там уже приделано взаимодействие с приложением, не знаю правда, что с производительносьтью.


Там IRP canceling не худо бы починить. И я не уверен, что этот драйвер будет легко подписать: ребята довольно вольно обращаются с WDM'овским API. Большая его часть для минипортов запрещена.
Re[19]: имитация сетевого интерфейса
От: k732  
Дата: 09.11.07 16:56
Оценка:
Pzz, ну в общем я пришел к выводу, что все-равно придется писать дровину.
Только вопрос — Tap-Win32 — это единственное достойное решения на сегодняшний день под винду ?
Re[19]: имитация сетевого интерфейса
От: k732  
Дата: 09.11.07 16:58
Оценка:
P.S.S И кстати где можно почитать хорошее описание для Ndis кроме как DDK — у меня проблеммы с английским, да и DDK довольно плохо структурирован...
Re[20]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 09.11.07 17:04
Оценка:
Здравствуйте, k732, Вы писали:

K>Pzz, ну в общем я пришел к выводу, что все-равно придется писать дровину.

K>Только вопрос — Tap-Win32 — это единственное достойное решения на сегодняшний день под винду ?

Я другого не знаю. И сам его юзаю. Но у меня запланированно переписать его нах, когда руки дойдут.

Насчет DDK — я не знаю другого выхода, кроме как учить английский. На самом деле, надо просто не бояться незнакомых слов. В техническом тексте знакомых слов достаточно много, чтобы понимать смысл. Я сам так выучил: начал читать программистские книжки на английском, и язык постепенно усвоился.
Re[21]: имитация сетевого интерфейса
От: k732  
Дата: 09.11.07 17:09
Оценка:
Pzz>Я другого не знаю. И сам его юзаю. Но у меня запланированно переписать его нах, когда руки дойдут.
Pzz, ты не мог бы привести простейший пример работы с ним ? Тоесть просто отправить пакет и принять ответ.

А там если заработает — буду разбираться...
Re[22]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 09.11.07 18:03
Оценка:
Здравствуйте, k732, Вы писали:

Pzz>>Я другого не знаю. И сам его юзаю. Но у меня запланированно переписать его нах, когда руки дойдут.

K>Pzz, ты не мог бы привести простейший пример работы с ним ? Тоесть просто отправить пакет и принять ответ.

K>А там если заработает — буду разбираться...


Ну во-первых, драйвер надо слегка попатчить, чтобы он мог сосуществовать с другими такими же:

1) Придумываем, во что мы переименуем:
1.1) Драйвер. Было tap0801.sys, стало — ?
1.2) Суффикс имени устройства. Было ".tap", стало — ?

Примечание, у меня драйвер назывался tap0801, у Вас циферка может быть чуть другая.

2) Находим ВСЕ упоминания tap0801 во ВСЕХ файлах, (независимо от наличия у них суффикса) и заменяем на выбранное имя. Проверяем еще раз с помощью grep'а, что ничего не забыли и нигде не опечатались — а то потом будет муторно это отлаживать.

3) Правим информацию о продукте — нехорошо использовать измененный драйвер под чужим именем
3.1) DeviceDescription и Provider в .INF-файлах
3.2) PRODUCT_STRING в tap-win32/constants.h
3.2) VER_COMPANYNAME_STR, VER_FILEDESCRIPTION_STR в tap-win32/resource.rc

4) В tap-win32/common.h заменяем TAPSUFFIX с ".tap" на выбранный нами. Если выбранный нами суффикс длинный, заменяем также NAME_BUFFER_SIZE в tap-win32/tapdrvr.c с 80 на, скажем, 260 (длиннее все равно не бывает)

Теперь как с ним работать. Для начала его надо найти. Я лично, чтобы упростить себе жизнь, пошел следующим путем:

1) Имя драйвера (с точки зрения CreateFile()) выглядит так:

\\.\INTERFACE.SUFFIX

INTERFACE — это имя сетевого интерфейса, оно назначается при инсталляции. SUFFIX — это тот суффукс, который был .tap, и который мы чем-то заменили

2) Получить список всех сетевых интерфейсов с именами можно с помощью функции GetAdaptersInfo(). Она возвращает список структур IP_ADAPTER_INFO, нас интересует поле AdapterName. Под XP оно выглядит как GUID.

3) Пробегаемся по всему списку, и пытаемся сделать CreateFile() на см. выше. Чтобы случайно не открыть что-то не то, я выбрал в качестве суффукса с
сгенеренный мной GUID. В результате имя довольно длинное, затем-то и понадобилось поменять NAME_BUFFER_SIZE (см. выше).

4) Открыв устройство, надо бы сказать системе, что "в него воткнули сетевой кабель". Для этого делаем DeviceIoControl:
* код — TAP_IOCTL_SET_MEDIA_STATUS (описан в tap-win32/common)
* данные — ULONG. 1 — кабель воткнули, 0 — отключили

5) Посылать/принимать очень просто: WriteFile() записывает пакет, который с точки зрения системы как-бы придет из виртуальной сетевой карточки. ReadFile() наоборот, выгребает очередной пакет, который система послала в интерфейс.

6) Для эффективности следует использовать overlapped I/O, и сразу заскедулить несколько overlapped ReadFile(). По мере того, как пакеты проходят, надо подсовывать новые ReadFile(), чтобы все время несколько из них были активны.

7) Для записи делать этого, насколько я помню, нет особого смысла: драйвер завершает запрос на запись (IRP_MJ_WRITE) сразу, по мере получения.

8) Получаемые/отправляемые пакеты по дефолту имеют Ethernet'овский заголовок. Существует и другой режим, но про него я рассказывать не буду

P.S. Драйвер GPL'ный, а это значит, что его измененные исходники надо распостранять вместе с продуктом. Однако это не означает, что надо распостранять исходники самого продукта, если только продукт не является "производной работой" (derived work) от драйвера.

P.P.S. Я тут распинаюсь, а следовало бы отправить Вас почитать исходники OpenVPN в качестве примера работы с ихним же драйвером. Но ладно, раз уж набил, проще отправить
Re[23]: имитация сетевого интерфейса
От: k732  
Дата: 09.11.07 20:05
Оценка:
Pzz>Ну во-первых, драйвер надо слегка попатчить, чтобы он мог сосуществовать с другими такими же:

Pzz>1) Придумываем, во что мы переименуем:

Pzz>1.1) Драйвер. Было tap0801.sys, стало — ?
Pzz>1.2) Суффикс имени устройства. Было ".tap", стало — ?

Pzz>Примечание, у меня драйвер назывался tap0801, у Вас циферка может быть чуть другая.


Pzz>2) Находим ВСЕ упоминания tap0801 во ВСЕХ файлах, (независимо от наличия у них суффикса) и заменяем на выбранное имя. Проверяем еще раз с помощью grep'а, что ничего не забыли и нигде не опечатались — а то потом будет муторно это отлаживать.


Pzz>3) Правим информацию о продукте — нехорошо использовать измененный драйвер под чужим именем

Pzz>3.1) DeviceDescription и Provider в .INF-файлах
Pzz>3.2) PRODUCT_STRING в tap-win32/constants.h
Pzz>3.2) VER_COMPANYNAME_STR, VER_FILEDESCRIPTION_STR в tap-win32/resource.rc

Pzz>4) В tap-win32/common.h заменяем TAPSUFFIX с ".tap" на выбранный нами. Если выбранный нами суффикс длинный, заменяем также NAME_BUFFER_SIZE в tap-win32/tapdrvr.c с 80 на, скажем, 260 (длиннее все равно не бывает)


Ну на самом деле зачем это делать ? Если есть готовые имена — пусть они и будут — проект не для продажи

Pzz>Теперь как с ним работать. Для начала его надо найти. Я лично, чтобы упростить себе жизнь, пошел следующим путем:


Pzz>1) Имя драйвера (с точки зрения CreateFile()) выглядит так:


Pzz> \\.\INTERFACE.SUFFIX


Pzz>INTERFACE — это имя сетевого интерфейса, оно назначается при инсталляции. SUFFIX — это тот суффукс, который был .tap, и который мы чем-то заменили


Pzz>2) Получить список всех сетевых интерфейсов с именами можно с помощью функции GetAdaptersInfo(). Она возвращает список структур IP_ADAPTER_INFO, нас интересует поле AdapterName. Под XP оно выглядит как GUID.


Pzz>3) Пробегаемся по всему списку, и пытаемся сделать CreateFile() на см. выше. Чтобы случайно не открыть что-то не то, я выбрал в качестве суффукса с

Pzz>сгенеренный мной GUID. В результате имя довольно длинное, затем-то и понадобилось поменять NAME_BUFFER_SIZE (см. выше).
А если я знаю его символическую ссылку — зачем пытаться открыть все ?

Pzz>4) Открыв устройство, надо бы сказать системе, что "в него воткнули сетевой кабель". Для этого делаем DeviceIoControl:

Pzz> * код — TAP_IOCTL_SET_MEDIA_STATUS (описан в tap-win32/common)
Pzz> * данные — ULONG. 1 — кабель воткнули, 0 — отключили

Вот за это огромное спасибо — блише к телу

Pzz>5) Посылать/принимать очень просто: WriteFile() записывает пакет, который с точки зрения системы как-бы придет из виртуальной сетевой карточки. ReadFile() наоборот, выгребает очередной пакет, который система послала в интерфейс.


Тоесть отдельный поток на чтение ?

Pzz>6) Для эффективности следует использовать overlapped I/O, и сразу заскедулить несколько overlapped ReadFile(). По мере того, как пакеты проходят, надо подсовывать новые ReadFile(), чтобы все время несколько из них были активны.


Не совсем понял
Pzz>7) Для записи делать этого, насколько я помню, нет особого смысла: драйвер завершает запрос на запись (IRP_MJ_WRITE) сразу, по мере получения.
Pzz>8) Получаемые/отправляемые пакеты по дефолту имеют Ethernet'овский заголовок. Существует и другой режим, но про него я рассказывать не буду

Pzz>P.S. Драйвер GPL'ный, а это значит, что его измененные исходники надо распостранять вместе с продуктом. Однако это не означает, что надо распостранять исходники самого продукта, если только продукт не является "производной работой" (derived work) от драйвера.


Ну это для меня не важно

Pzz>P.P.S. Я тут распинаюсь, а следовало бы отправить Вас почитать исходники OpenVPN в качестве примера работы с ихним же драйвером. Но ладно, раз уж набил, проще отправить


Спасибо
Re[24]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 09.11.07 20:19
Оценка:
Здравствуйте, k732, Вы писали:

Pzz>>4) В tap-win32/common.h заменяем TAPSUFFIX с ".tap" на выбранный нами. Если выбранный нами суффикс длинный, заменяем также NAME_BUFFER_SIZE в tap-win32/tapdrvr.c с 80 на, скажем, 260 (длиннее все равно не бывает)


K>Ну на самом деле зачем это делать ? Если есть готовые имена — пусть они и будут — проект не для продажи


Чтобы если Вы вдруг поставите какую-нибудь софтину, которая притаскивает с собой этот драйвер, они не столкнулись. Просто разумная мера предосторожности, как мыть руки перед едой.

Pzz>>3) Пробегаемся по всему списку, и пытаемся сделать CreateFile() на см. выше. Чтобы случайно не открыть что-то не то, я выбрал в качестве суффукса с

Pzz>>сгенеренный мной GUID. В результате имя довольно длинное, затем-то и понадобилось поменять NAME_BUFFER_SIZE (см. выше).
K>А если я знаю его символическую ссылку — зачем пытаться открыть все ?

Та часть его имени, которая берется из имени адаптера, назначается системой при инсталляции драйвера. Т.е., заранее ее знать нельзя.

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

Pzz>>5) Посылать/принимать очень просто: WriteFile() записывает пакет, который с точки зрения системы как-бы придет из виртуальной сетевой карточки. ReadFile() наоборот, выгребает очередной пакет, который система послала в интерфейс.


K>Тоесть отдельный поток на чтение ?


Совсем не обязательно.

Pzz>>6) Для эффективности следует использовать overlapped I/O, и сразу заскедулить несколько overlapped ReadFile(). По мере того, как пакеты проходят, надо подсовывать новые ReadFile(), чтобы все время несколько из них были активны.


K>Не совсем понял


Вы знаете, как работает overlapped I/O. Вы заказываете операцию, она там варится внутри операционной системы. Когда операция чем-нибудь кончается, Вам об этом сообщают через структуру OVERLAPPED.

Так вот, можно заказать следуюшую операцию, не дожидаясь окончания предыдущей. Каждой заказанной, но не оконченной операции соответствует IRP в драйверной очереди. Если поддерживать эту очередь непустой, то при появлении пакета драйвер кидает его прямо в IRP и завершает запрос. Иначе драйвер кладет пакет себе за щеку, и выгребает оттуда по приходу следующего запроса.

Если Ваша программа читает пакеты по одному, она будет просыпаться на каждый пакет, выгребать его и т.д. Если же она запустила сразу несколько запросов, то она проснется по первому, но выгрести сможет одним махом все. Это будет работать быстрее при большом потоке данных (при маленькой загрузке особой разницы не будет).

Надо накидать этих запросов сразу с запасом (я пока накидываю 16, но я никогда всерьез не тьюнил это место), и по мере окончания предыдущих докидываю соответствующее количество новых.
Re[25]: имитация сетевого интерфейса
От: k732  
Дата: 09.11.07 20:28
Оценка:
Pzz>Чтобы если Вы вдруг поставите какую-нибудь софтину, которая притаскивает с собой этот драйвер, они не столкнулись. Просто разумная мера предосторожности, как мыть руки перед едой.
разумно

Pzz>Можно, конечно, перефигачить драйвер таким образом, чтобы его символическая ссылка не зависила от имени интерфейса, и была константой. Я выбрал динамический поиск, т.к. это позволяет мне при необходимости легко добавить в систему больше одной виртуальной сетевой карты.

понятно

K>>Тоесть отдельный поток на чтение ?

Pzz>Совсем не обязательно.
Pzz>>>6) Для эффективности следует использовать overlapped I/O, и сразу заскедулить несколько overlapped ReadFile(). По мере того, как пакеты проходят, надо подсовывать новые ReadFile(), чтобы все время несколько из них были активны.
Pzz>Вы знаете, как работает overlapped I/O. Вы заказываете операцию, она там варится внутри операционной системы. Когда операция чем-нибудь кончается, Вам об этом сообщают через структуру OVERLAPPED.

Но при этом нужно ждать на событии и если оно произошло — опрашивать GetOverlappedResult — тоесть полюбому вычитывающий поток

Pzz>Так вот, можно заказать следуюшую операцию, не дожидаясь окончания предыдущей. Каждой заказанной, но не оконченной операции соответствует IRP в драйверной очереди. Если поддерживать эту очередь непустой, то при появлении пакета драйвер кидает его прямо в IRP и завершает запрос. Иначе драйвер кладет пакет себе за щеку, и выгребает оттуда по приходу следующего запроса.


если 16 запросов — то 16 потоков. Может я чего-то не совсем понимаю ?
Re[26]: имитация сетевого интерфейса
От: Pzz Россия https://github.com/alexpevzner
Дата: 09.11.07 20:40
Оценка:
Здравствуйте, k732, Вы писали:

Pzz>>Вы знаете, как работает overlapped I/O. Вы заказываете операцию, она там варится внутри операционной системы. Когда операция чем-нибудь кончается, Вам об этом сообщают через структуру OVERLAPPED.


K>Но при этом нужно ждать на событии и если оно произошло — опрашивать GetOverlappedResult — тоесть полюбому вычитывающий поток


Мне трудно себе представить программу, которой всегда есть чем себя занять. Обычно все-таки в программе предусмотрено ожидание новой работы, когда старая закончилась. Окончание overlaped i/o — такая же новая работа, как и всякая другая.

Pzz>>Так вот, можно заказать следуюшую операцию, не дожидаясь окончания предыдущей. Каждой заказанной, но не оконченной операции соответствует IRP в драйверной очереди. Если поддерживать эту очередь непустой, то при появлении пакета драйвер кидает его прямо в IRP и завершает запрос. Иначе драйвер кладет пакет себе за щеку, и выгребает оттуда по приходу следующего запроса.


K>если 16 запросов — то 16 потоков. Может я чего-то не совсем понимаю ?


Что мешает поделить один Event между всеми OVERLAPPED'ами? Когда Event становится просигналенным, просто просматриваете по кругу относящиеся к делу OVERLAPPED'ы в поисках таких, для которых HasOverlappedIoCompleted() возвращает TRUE (или чего он там возвращает в таких случаях, я не помню).

Чтобы не просматривать ВСЕ OVERLAPPED'ы, я пользуюсь тем фактом, что Tap-Win32 завершает запросы на запись в порядке поступления. Т.е., если 5-й запрос еще не завершен, на 6-й и далее можно не смотреть.

Т.е., хватает одного потока. У меня вообще вся программа крутится в одном потоке, с централизованным диспетчером событий. А у меня кроме этого тун-тапа много чего еще есть в программе — несколько UDP-портов, несколько named pipe, таймеры и прочая муть Это значительно удобнее, чем городить многопоточность и разбираться с синхронизацией.

При желании можно использовать Completion Port — он автоматизирует часть перечисленной выше работы, и заодно умеет разбрасывать обработку по нескольким потокам. Однако им достаточно сложно пользоваться.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.