Добро пожаловать! Это — архивная версия форумов на «Хакер.Ru». Она работает в режиме read-only.
 

[C++] Мультиплексирование SOCKET и stdin

Пользователи, просматривающие топик: none

Зашли как: Guest
Все форумы >> [Компилируемые языки] >> [C++] Мультиплексирование SOCKET и stdin
Имя
Сообщение << Старые топики   Новые топики >>
[C++] Мультиплексирование SOCKET и stdin - 2009-05-03 23:54:26.486666   
northsoft

Сообщений: 25
Оценки: 0
Присоединился: 2007-12-20 10:05:03.033333
Требуется мультиплексирование серверного сокета и стандартного потока ввода:
Сервер-демон запускается, прислушивается к порту. Если приходит входящее соединение, то сервер для него создает поток и дальнейшая работа производится уже вне основного потока.
Если получен ввод на консоль - завершить работу.
Все действия должны предприниматься незамедлительно. Поэтому требуется мультиплексирование как сетевого сокета, так и стандартного потока ввода.



В UNIX для этого обычно используется select. Однако в Windows функция select входит в состав библиотеки WinSock 2 и поддерживает мультиплексирование исключительно сетевых сокетов. После активного использования Google я нашел функцию WaitForMultipleObjects, которая поддерживает мультиплексирование консольного ввода вывода и событий. С помощью функции WSAEventSelect я создаю дескриптор, совместимый с событийным мультиплексором и сохраняю его в массив типа HANDLE[]. Туда же, на "соседнюю полочку", кладу дескриптор _fileno(stdin).

WaitForMultipleObjects при этом возвращает WAIT_FAILED, GetLastError возвращает ERROR_INVALID_HANDLE. Причем если не добавлять _fileno(stdin), то всё работает прекрасно, однако с не меньшим успехом я мог бы воспользоваться и уже привычным мне select.

Ну и код напоследок.

#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;winsock2.h&gt; int main(int argc, char *argv[], char **env){ char *ip; DWORD wfmret; int cycle_accept; int port; HANDLE eventHandle; HANDLE wfm[2]; SOCKET *s; WSADATA wsaData; struct sockaddr_in service; cycle_accept=0; ip=malloc(sizeof(char)*10); memset(ip,0,10); strncpy_s(ip,10,"127.0.0.1",10); port=91462; WSAStartup(MAKEWORD(2,2),&wsaData); s=malloc(sizeof(SOCKET)); *s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); service.sin_family=AF_INET; service.sin_addr.s_addr=inet_addr(ip); service.sin_port=htons(port); bind(*s,(SOCKADDR *)&service,sizeof(service)); listen(*s,1); cycle_accept=1; while(cycle_accept==1){ eventHandle=WSACreateEvent(); WSAEventSelect(*s,eventHandle,FD_ACCEPT); wfm[0]=eventHandle; wfm[1]=_fileno(stdin); wfmret=WaitForMultipleObjects(2,wfm,FALSE,5000); WSACloseEvent(eventHandle); if(wfmret==-1){ printf("Error code %d\n",GetLastError()); getchar(); cycle_accept=0; } } shutdown(*s,SD_BOTH); closesocket(*s); free(ip); free(s); return 0; }
Post #: 1
RE: [C++] Мультиплексирование SOCKET и stdin - 2009-05-04 00:00:47.083333   
northsoft

Сообщений: 25
Оценки: 0
Присоединился: 2007-12-20 10:05:03.033333
(проблема собственно говоря в том, что приведенный исходник не работает как надо, WaitForMultipleObjects() возвращает WAIT_FAILED, и нужно как-то приучить WaitForMultipleObjects работать со stdin).
Post #: 2
RE: [C++] Мультиплексирование SOCKET и stdin - 2009-05-04 10:21:58.200000   
rgo

Сообщений: 7170
Оценки: 281
Присоединился: 2004-09-25 05:14:25
Гыы. За все эти проблемы я и ненавижу вендовс. Сталкивался, знаю… Решил путём использования вендового порта glib. Там очень неплохо асинхронный ввод/вывод сделан.
Post #: 3
RE: [C++] Мультиплексирование SOCKET и stdin - 2009-05-04 19:35:49.136666   
northsoft

Сообщений: 25
Оценки: 0
Присоединился: 2007-12-20 10:05:03.033333
П-и-п-е-ц…
Кстати. Проблему решил использованием STD_INPUT_HANDLE вместо _fileno(stdin).
Теперь стало проблем еще больше. Мультиплексор радостно сообщает, что на консоли появился ввод, хотя на консоль я НИЧЕГО не вводил, или при подключении через Telnet мультиплексор один раз как положено сообщает о наличии подключения, я принимаю (accept) соединение и вышвыриваюсь в отдельный поток. А на следующую итерацию цикла мультиплексор опять срабатывает на сокет, причем, что естественно, я пытаюсь принять соединение (перед этим вырубив блокирующий режим, ioctlsocket(s,FIONBIO,адрес по которому лежит единичко)), и естественно я получаю от ворот поворот, WSAGetLastError() возвращает EWOULDBLOCK. Однако какого хрена мультиплексор срабатывает на уже принятое соединение…
В жизни бы не подумал, что с Winsock2 можно поиметь столько любви…
Post #: 4
Страниц:  [1]
Все форумы >> [Компилируемые языки] >> [C++] Мультиплексирование SOCKET и stdin







Связаться:
Вопросы по сайту / xakep@glc.ru

Предупреждение: использование полученных знаний в противозаконных целях преследуется по закону.