[C++] Мультиплексирование SOCKET и stdin
Пользователи, просматривающие топик: none
|
Зашли как: Guest
|
Имя |
Сообщение |
<< Старые топики Новые топики >> |
|
|
[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 <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
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;
}
|
|
|
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).
|
|
|
RE: [C++] Мультиплексирование SOCKET и stdin - 2009-05-04 10:21:58.200000
|
|
|
rgo
Сообщений: 7170
Оценки: 281
Присоединился: 2004-09-25 05:14:25
|
Гыы. За все эти проблемы я и ненавижу вендовс. Сталкивался, знаю… Решил путём использования вендового порта glib. Там очень неплохо асинхронный ввод/вывод сделан.
|
|
|
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 можно поиметь столько любви…
|
|
|
|
|