Windows网络编程:select的基本使用

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
);

 

参数说明:

nfds: Berkeley 套接字兼容,没有什么作用,忽略
readfds: 检查设置的套接字是否可以读,可以忽略

     writefds检查设置的套接字是否可以写,可以忽略

      exceptfds: 检查套接字的错timeoutselect等待的时间。NULL:阻塞状态;初始为{0,0}时,立即返回

      返回值:返回fd_set中的套接字句柄数;0:等待时间超时; SOCKET_ERROR发生错误,使用WSAGetLastError得具体的错误代码。

 

操作fd_set的宏:

FD_CLR(s, *set)

set中移除

FD_ISSET(s, *set)

如果sset的成员返回非0,否则返回0

FD_SET(s, *set)

 s添加到set

FD_ZERO(*set)

初始化setnull


使用select使用的几个步骤

1.       使用FD_ZEROfd_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 ;
}

 

你可能感兴趣的:(Windows网络编程:select的基本使用)