Windows网络编程:select的基本使用
client_sockselect的基本使用
函数原型:
int
select(
__in int nfds,
__inout fd_set * readfds,
__inout fd_set * writefds,
__inout fd_set * exceptfds,
__in const struct timeval * timeout
);
__in int nfds,
__inout fd_set * readfds,
__inout fd_set * writefds,
__inout fd_set * exceptfds,
__in const struct timeval * timeout
);
参数说明:
nfds: 与Berkeley 套接字兼容,没有什么作用,忽略
readfds: 检查设置的套接字是否可以读,可以忽略
writefds:检查设置的套接字是否可以写,可以忽略
exceptfds: 检查套接字的错timeout:select等待的时间。NULL:阻塞状态;初始为{0,0}时,立即返回
返回值:返回fd_set中的套接字句柄数;0:等待时间超时; SOCKET_ERROR发生错误,使用WSAGetLastError获得具体的错误代码。
操作fd_set的宏:
FD_CLR(s, *set)
从set中移除
FD_ISSET(s, *set)
如果s是set的成员返回非0,否则返回0
FD_SET(s, *set)
把 s添加到set中
FD_ZERO(*set)
初始化set为null
使用select使用的几个步骤
1. 使用FD_ZERO对fd_set结构清空
2. 添加套接字句柄到fd_set中,使用FD_SET宏
3. 调用select
4. 使用FD_ISSET判断是哪个套接字
5. 进行读写操作,然后返回步骤1
下面是一个简单例子
#include
<
winsock2.h
>
#include < stdio.h >
#pragma comment(lib, " ws2_32.lib " )
#define LISTEN_PORT 5080
#define RECV_BUFF_SIZE 512
int main( void )
{
WSADATA wsadata;
int ret;
SOCKET listen_sock;
SOCKET client_sock;
SOCKADDR_IN listen_addr;
SOCKADDR_IN in_addr;
int in_add_len = sizeof (in_addr);
fd_set fdread;
char recv_buff[RECV_BUFF_SIZE];
ret = WSAStartup(MAKEWORD( 2 , 2 ), & wsadata);
if ( 0 != ret)
{
printf( " WSAStartup error:%d.\n " , WSAGetLastError());
return - 1 ;
}
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == listen_sock)
{
printf( " socket error:%d.\n " , WSAGetLastError());
goto rettag1;
}
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_addr.sin_port = htons(LISTEN_PORT);
ret = bind(listen_sock, (SOCKADDR * ) & listen_addr, sizeof (listen_addr));
if (SOCKET_ERROR == ret)
{
printf( " bind error:%d.\n " , WSAGetLastError());
goto rettag2;
}
ret = listen(listen_sock, 5 );
if (SOCKET_ERROR == ret)
{
printf( " listen error:%d.\n " , WSAGetLastError());
goto rettag2;
}
client_sock = accept(listen_sock, (SOCKADDR * ) & in_addr, & in_add_len);
if (INVALID_SOCKET == client_sock)
{
printf( " accept error:%d.\n " , WSAGetLastError());
goto rettag2;
}
else
{
printf( " accept client:%s:%d.\n " , inet_ntoa(in_addr.sin_addr), in_addr.sin_port);
}
while ( 1 )
{
FD_ZERO( & fdread);
FD_SET(client_sock, & fdread);
ret = select( 0 , & fdread, NULL, NULL, NULL);
if (SOCKET_ERROR == ret)
{
printf( " select error:%d.\n " , WSAGetLastError());
}
if (ret > 0 )
{
if (FD_ISSET(client_sock, & fdread))
{
ret = recv(client_sock, recv_buff, RECV_BUFF_SIZE, 0 );
if (SOCKET_ERROR == ret)
{
printf( " recv error:%d.\n " , WSAGetLastError());
}
else if ( 0 == ret)
{
printf( " recv, socket closed.\n " );
break ;
}
else
{
printf( " receive data:\n%s\n " , recv_buff);
}
}
}
}
closesocket( client_sock );
rettag2:
ret = closesocket(listen_sock);
if (SOCKET_ERROR == ret)
{
printf( " closesocket error:%d.\n " , WSAGetLastError());
}
rettag1:
ret = WSACleanup();
if ( 0 != ret)
{
printf( " WSACleanup error:%d.\n " , WSAGetLastError());
return - 1 ;
}
return 0 ;
}
#include < stdio.h >
#pragma comment(lib, " ws2_32.lib " )
#define LISTEN_PORT 5080
#define RECV_BUFF_SIZE 512
int main( void )
{
WSADATA wsadata;
int ret;
SOCKET listen_sock;
SOCKET client_sock;
SOCKADDR_IN listen_addr;
SOCKADDR_IN in_addr;
int in_add_len = sizeof (in_addr);
fd_set fdread;
char recv_buff[RECV_BUFF_SIZE];
ret = WSAStartup(MAKEWORD( 2 , 2 ), & wsadata);
if ( 0 != ret)
{
printf( " WSAStartup error:%d.\n " , WSAGetLastError());
return - 1 ;
}
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == listen_sock)
{
printf( " socket error:%d.\n " , WSAGetLastError());
goto rettag1;
}
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_addr.sin_port = htons(LISTEN_PORT);
ret = bind(listen_sock, (SOCKADDR * ) & listen_addr, sizeof (listen_addr));
if (SOCKET_ERROR == ret)
{
printf( " bind error:%d.\n " , WSAGetLastError());
goto rettag2;
}
ret = listen(listen_sock, 5 );
if (SOCKET_ERROR == ret)
{
printf( " listen error:%d.\n " , WSAGetLastError());
goto rettag2;
}
client_sock = accept(listen_sock, (SOCKADDR * ) & in_addr, & in_add_len);
if (INVALID_SOCKET == client_sock)
{
printf( " accept error:%d.\n " , WSAGetLastError());
goto rettag2;
}
else
{
printf( " accept client:%s:%d.\n " , inet_ntoa(in_addr.sin_addr), in_addr.sin_port);
}
while ( 1 )
{
FD_ZERO( & fdread);
FD_SET(client_sock, & fdread);
ret = select( 0 , & fdread, NULL, NULL, NULL);
if (SOCKET_ERROR == ret)
{
printf( " select error:%d.\n " , WSAGetLastError());
}
if (ret > 0 )
{
if (FD_ISSET(client_sock, & fdread))
{
ret = recv(client_sock, recv_buff, RECV_BUFF_SIZE, 0 );
if (SOCKET_ERROR == ret)
{
printf( " recv error:%d.\n " , WSAGetLastError());
}
else if ( 0 == ret)
{
printf( " recv, socket closed.\n " );
break ;
}
else
{
printf( " receive data:\n%s\n " , recv_buff);
}
}
}
}
closesocket( client_sock );
rettag2:
ret = closesocket(listen_sock);
if (SOCKET_ERROR == ret)
{
printf( " closesocket error:%d.\n " , WSAGetLastError());
}
rettag1:
ret = WSACleanup();
if ( 0 != ret)
{
printf( " WSACleanup error:%d.\n " , WSAGetLastError());
return - 1 ;
}
return 0 ;
}