![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| wvlg |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 17 Регистрация: 2.6.2008 Репутация: нет Всего: нет |
Изначально задача стоит так:
Происходит работа с драйвером сетевых устройств. Ставиться фильтр на перехват пакетов (например, по IP и порту назначения удаленного хоста, т.е фильтруются исходящие на него и приходящие с него пакеты). Далее, необходимо определить когда пользователь начал работу с удаленным хостом (началом работы считается первый перехваченный пакет К хосту). После такого пакета необходимо: 1. "запомнить" порт(локальный) с которого он отправлен. 2. Создать поток, которому в дальнейшем будут передаваться на обработку все пакеты, отосланные с этого локального порта (и все пакеты, корые ему будут адресованы). Этот поток будет их обрабатывать (неважно как, просто производить действия, например, заменять полученные\отосланные байты данных) 3. После обработки пакета его необходимо отправить получателю. (Или проигнорировать) 4. Вопрос встал в том КАК эти самые пакеты передавать потокам-обработчикам. А потом обратно главному потоку, чтобы он непосредственно их отправил. Дело в том, что пользователь может открыть несколько сессий работы с сервером. (Т.е. отправлять\получать с\на разных локальных портов пакеты на\с удаленный хост). Каждая такая "сессия" должна обрабатываться отдельным потоком программы. (как я себе представляю). Далее полагаю, что задача основного потока. Определить ПортПользователя. Создать поток для его обработки, если такового еще нет. Передать пакет на обработку. Я предположил ввести контейнер FIFO для работы с каждым таким потоком. Т.е. пришел пакет такого-то ПортаПользователя-его "пихаем" в такой-то контейнер. А далее поток "сам с ним работает". Встал вопрос. Не может ли возникнуть конфликта при одновременном обращении к такому контейнеру? Т.е. может возникнуть момент, когда в таком контейнере "накопиться" определенное число пакетов и к нему (контейнеру) могут одновременно обратиться основной поток (чтобы положить туда очередной пакет) и поток обрабатывающий пакеты, лежащие там. Будет ли конфликт при таком одновременном обращении? (вопрос кажется странным, т.к. в любой момент времени два потока все же не работают одновременно(с такими контейнерами), по идее не должно быть проблем, но все же...) Кроме всего прочего необходимо будет реализовать такой же FIFO контейнер куда потоки, обрабатывающие пакеты будут ложить уже готовые к отправке пакеты, отправкой которых будет заниматься основной поток. Возможно, я выбрал не самый лучший способ организации обработки пакетов, не отказался бы от советов на эту тему. Это сообщение отредактировал(а) wvlg - 6.6.2008, 23:36 |
|||
|
||||
| wvlg |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 17 Регистрация: 2.6.2008 Репутация: нет Всего: нет |
Задам немного другой вопрос. Также относящийся сюда.
Каким образом организовать контейнер в который можно записывать одним потоком когда угодно, а вторым из него же брать когда угодно? Такой контейнер, чтобы не было конфликтов одновременного доступа и, самое главное не было ЗАДЕРЖКИ на запись в такой контейнер (хотя бы именно на запись). Т.е. поток, записывающий данные в контейнер, не должен "думать" занят тот или нет. Как такое реализовать? Контейнер типа FIFO. Это сообщение отредактировал(а) wvlg - 7.6.2008, 10:51 |
|||
|
||||
| sparn |
|
||||||||||||||
|
Новичок Профиль Группа: Участник Сообщений: 21 Регистрация: 11.5.2006 Репутация: нет Всего: 1 |
Конфликт будет если не использовать критические секции для защиты контейнера от одновременного доступа из разных потоков. Как может возникнуть конфликт: "клиентский" поток пытается добавить в конец очереди пакет, в этот момент обрабатывающий поток выбирает один или все первые пакеты, как результат, потери пакетов+утечки памяти или неверные смещения/указатели+исключительные ситуации. Из личного опыта и исходя из закона Мерфи если будет хоть малейшая лазейка для рассинхронизации, то эта гадость обязательно случится. Что касается "в любой момент времени два потока все же не работают одновременно" - так было на одноядерных, однопроцессорных машинах, сегодня даже на домашних компьютерах в один и тот же момент могут работать несколько потоков(как следствие многоядерных процессоров). Добавлено через 4 минуты и 41 секунду
Используя механизм критических секций(ищи в msdn описание CRITICAL_SECTION, EnterCriticalSection, LeaveCriticalSection, InitializeCriticalSection, DeleteCriticalSection). Абсолютно без задержек это реализовать невозможно(т.к. в случае если один поток зашел в критическую секцию второй должен ждать пока первый не выйдет из неё), но можно свести их к минимуму. пример FIFO для передачи пакетов между потоками: делаем нужные объявления:
не забываем инициализировать:
добавляем пакет в конец списка таким образом:
выбираем первый пакет из очереди таким образом:
и по завершении работы не забываем очистить список и вызвать:
|
||||||||||||||
|
|||||||||||||||
| sparn |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 21 Регистрация: 11.5.2006 Репутация: нет Всего: 1 |
Модель "коннект-поток" не очень удачная(или совсем неудачная), не зря ведь придумываются всякие асинхронные сокеты. Чем больше потоков тем медленнее происходит переключение между ними, тем больше процессорного времени теряется впустую, более того во всех ОС есть максимальное количество потоков. Количество обрабатывающих потоков должно ИМХО зависеть лишь от количества процессоров/ядер(т.е например: кол-во_обрабатывающих_потоков = кол-во_ядер * 2).
Думаю тут уместно будет выделить для отправки пакетов отдельный поток. |
||||
|
|||||
| wvlg |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 17 Регистрация: 2.6.2008 Репутация: нет Всего: нет |
2 sparn
Спасибо за ответы!!! Теперь хоть точно знаю, что при работе с очередью "будут проблемы" (хотя один знакомый утверждал, что одновременное обращение "исключается самой структурой FIFO контейнеров"). Вот только не совсем понятным остается как же тогда обрабатывать каждый коннект... Честно говоря с трудом представляю как один поток смог бы обрабатывать несколько коннектов. Т.е. работал бы с пакетами, адресованными\посланными на\с разные порты... Дело в том, что работа такого потока как раз и зависит от содержания пакетов... Могу сказать, что в пакетах приходит машинный код, который необходимо будет исполнить. Поэтому и были мысли о том, чтобы для каждого коннекта создавать отдельный поток... Думал я и об ограничении при такой реализации. Но что поделать? Хотя было бы здорово, если бы возможно было обрабатывать данные в ограниченном количестве потоков, т.е. для каждого коннекта не создавать новый. Думается, можно уйти к решению с конечным числом потоков, если ввести какой-нибудь объект-исполнитель машинного кода. Т.е. есть объект, передаем ему строку на исполнение и этот объект хранит этот код и всегда его выполняет при вызове.... Хотя, наверное, тут необходимо все более детально изложить общую задачу, чтобы уйти от огромного количества потоков. |
|||
|
||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |