Shaitan-Devil
12.06.2009, 10:32
[INTRO]
Здравствуйте, юные хакиры. Сегодня я расскажу вам о неблокируемых(асинхронных) сокетах.
Сокеты поддерживают два режима: блокируемые(синхронные) и неблокируемые(асинхронные) . В чем же их основное отличие? Функции(send,recv и.т.д.) после объявления, ожидают окончания операции, а в неблокируемом режиме
если данные не приходят сразу, завершают свою работу. Одной из достойных замен неблокирующему режиму являются потоки.
[Создаем неблокируемый сокет]
Точнее переводим его в асинхронный режим
SCOKET s;
u_long c=1;
u_long i;
nRet = ioctlsocket(s, FIONBIO, (u_long *) &c);
Если сервер не послал нам ответ сразу, функции будут возвращать WSAEWOULDBLOCK. В принципе, моэно выполнять команду до получения результата. Т.е.
while ( !connect( s, (struct sockaddr *)&sa, sizeof(sa) ) != WSAEWOULDBLOCK )
{
connect(s,(struct sockaddr*)&sa,
sizeof(sa));
}
Но это приводит нас обратно к блокируемым сокетам. У нас другая цель. Поэтому, если нам нужно через определенное время посылать пинги или проверять есть ли данные в буфере, мы можем использовать ввод-вывод в WinSock.
[SELECT]
Это можно реализовать с помощью функции select(). Сама функция:
int select(
fd_set FAR * readfds,/*Возможность чтения*/
fd_set FAR * writefds,/*Возможность записи*/
fd_set FAR * exceptfds,/*Срочне данные*/
const struct timeval FAR * timeout/*Отсчет времени*/
);
Для работы с fd_set опеределены макросы
FD_ISSET(s, *set)/*Проверяет входит ли сокет в набор*/
FD_SET(s, *set)/*Добавляет сокет в набор*/
FD_CRL(s,*set)/*Удаляет сокет s из наборы*/
Итак, для примера напишем приложение проверяющее сокет на возможность записи
WSADATA WSAData;
if (WSAStartup(0x0202, &WSAData))
return 0;
SOCKET s;
sockaddr_in sa;
sa.sin_family=AF_INET;
sa.sin_port=htons(12345);
sa.sin_adrr.s_addr=inet_addr("127.0.0.1")
s=(AF_INET,SOCK_STREAM,0);
fd_set f;
int r;
char buff;
connect(s,(struct sockaddr *)&sa, sizeof(sa));
if(r=select(0,NULL,&f,NULL,NULL))=SOCKET_ERROR)
{
cout<<"Error";
}
if(FD_ISSET(s, &f))
{
send(s, buff, sizeof(buff),0);
}else{ cout<<"Error";}
[Неблокирующий connect]
В любом случае connect() остается неблокирющим. Но его можно перевести в неблокирющий режим функцией fcntl()
int flags = fcntl(s, F_GETFL, 0);
if(fcntl(s, F_SETFL, flags | O_NONBLOCK) ==SCOKET_ERROR)
{
cout<"Error";
}
if(connect(s, (struct sockaddr*)&sa, sizeof(sa)) !=SOCKET_ERROR)
{
if(errno == EINPROGRESS)
{
/*ту мы с помощью select() проверяем сокет на готовность*/
}
else
{
cout<<"Error";
}
}
else
{
/*
* Соединение было установлено за время
* системного вызова, работа продолжается
* традиционным способом.
*/
}
П.С. Есть еще несколько способов использования асинхронных сокетов, к примеру WSAAsyncSelect().
П.П.С Прошу строго не судить и высказывать свои замечания.
Здравствуйте, юные хакиры. Сегодня я расскажу вам о неблокируемых(асинхронных) сокетах.
Сокеты поддерживают два режима: блокируемые(синхронные) и неблокируемые(асинхронные) . В чем же их основное отличие? Функции(send,recv и.т.д.) после объявления, ожидают окончания операции, а в неблокируемом режиме
если данные не приходят сразу, завершают свою работу. Одной из достойных замен неблокирующему режиму являются потоки.
[Создаем неблокируемый сокет]
Точнее переводим его в асинхронный режим
SCOKET s;
u_long c=1;
u_long i;
nRet = ioctlsocket(s, FIONBIO, (u_long *) &c);
Если сервер не послал нам ответ сразу, функции будут возвращать WSAEWOULDBLOCK. В принципе, моэно выполнять команду до получения результата. Т.е.
while ( !connect( s, (struct sockaddr *)&sa, sizeof(sa) ) != WSAEWOULDBLOCK )
{
connect(s,(struct sockaddr*)&sa,
sizeof(sa));
}
Но это приводит нас обратно к блокируемым сокетам. У нас другая цель. Поэтому, если нам нужно через определенное время посылать пинги или проверять есть ли данные в буфере, мы можем использовать ввод-вывод в WinSock.
[SELECT]
Это можно реализовать с помощью функции select(). Сама функция:
int select(
fd_set FAR * readfds,/*Возможность чтения*/
fd_set FAR * writefds,/*Возможность записи*/
fd_set FAR * exceptfds,/*Срочне данные*/
const struct timeval FAR * timeout/*Отсчет времени*/
);
Для работы с fd_set опеределены макросы
FD_ISSET(s, *set)/*Проверяет входит ли сокет в набор*/
FD_SET(s, *set)/*Добавляет сокет в набор*/
FD_CRL(s,*set)/*Удаляет сокет s из наборы*/
Итак, для примера напишем приложение проверяющее сокет на возможность записи
WSADATA WSAData;
if (WSAStartup(0x0202, &WSAData))
return 0;
SOCKET s;
sockaddr_in sa;
sa.sin_family=AF_INET;
sa.sin_port=htons(12345);
sa.sin_adrr.s_addr=inet_addr("127.0.0.1")
s=(AF_INET,SOCK_STREAM,0);
fd_set f;
int r;
char buff;
connect(s,(struct sockaddr *)&sa, sizeof(sa));
if(r=select(0,NULL,&f,NULL,NULL))=SOCKET_ERROR)
{
cout<<"Error";
}
if(FD_ISSET(s, &f))
{
send(s, buff, sizeof(buff),0);
}else{ cout<<"Error";}
[Неблокирующий connect]
В любом случае connect() остается неблокирющим. Но его можно перевести в неблокирющий режим функцией fcntl()
int flags = fcntl(s, F_GETFL, 0);
if(fcntl(s, F_SETFL, flags | O_NONBLOCK) ==SCOKET_ERROR)
{
cout<"Error";
}
if(connect(s, (struct sockaddr*)&sa, sizeof(sa)) !=SOCKET_ERROR)
{
if(errno == EINPROGRESS)
{
/*ту мы с помощью select() проверяем сокет на готовность*/
}
else
{
cout<<"Error";
}
}
else
{
/*
* Соединение было установлено за время
* системного вызова, работа продолжается
* традиционным способом.
*/
}
П.С. Есть еще несколько способов использования асинхронных сокетов, к примеру WSAAsyncSelect().
П.П.С Прошу строго не судить и высказывать свои замечания.