套接字Select I/O模型

select模型

select(选择)模型是winsock中常见的I/O模型。之所以称其为“select模型”,是由于它的
“中心思想”是利用select函数,实现对I/O的管理!最初设计该模型时,主要面向的是某些使用
Unix操作系统的计算机,它们采用的是Berkeley套接字方案。select模型已经集成到Winsock1.1中。

1

.通过调用select函数可以确定一个或多个套接字的状态,判断套接字上是否有数据,或
者能否向一个套接字写入数据。 
 
int  select ( int  nfds,                                                    // 忽略
                fd_set FAR  * readfds,                                 // 等待可读性检查的套接字组的地址
                fd_set FAR  * writefds,                                // 等待可写性检查的套接字组的地址
                fd_set FAR  * exceptfds,                               // 等待错误检查的套接字组的地址
                 const   struct  timeval FAR  * timeout);          // struct timeval结构体地址,select() 最多等待的时间
// 返回值       0--超时,SOCKET_ERROR--失败
// 说明:此函数的作用是删除fd_set结构体中没有IO操作的套接字
/*
注意:在3个套接字组中至少有一个不为NULL;在非空集合中必须包含一个套接字句柄。
     如果timeout设为(0,0),select() 会立即返回,允许应用程序对select操作进行“轮询”。
     如:
        fd_set fdread;
        FD_ZERO(&fdread);
        FD_SET(s, &fdread);
        select(0, &fdread, NULL, NULL, NULL);
        if(FD_ISSET(s, &fdread))
        {
                //套接字可读
        }
*/


2 .管理套接字的结构体
定义:
typedef 
struct  fd_set {
        u_int   fd_count;               
/*  how many are SET?  */    // 元素的个数
        SOCKET  fd_array[FD_SETSIZE];    /*  an array of SOCKETs  */
} fd_set;

对struct fd_set结构体操作的宏
FD_SETSIZE              容量,指定fd_array数组大小,默认为64,也可自己修改宏
FD_ZERO(
* set )           置空,使数组的元素值都为3435973836,元素个数为0.
FD_SET(s, 
* set )         添加,向  struct  fd_set结构体添加套接字s
FD_ISSET(s, 
* set )       判断,判断s是否为  struct  fd_set结构体中的一员
FD_CLR(s, 
* set )         删除,从  struct  fd_set结构体中删除成员s    

3 .用Select模型获取网络事件

    FD_SET AllSockFd;        
// 装有所有的套接字
    FD_ZERO( & AllSockFd);
    AllSockFd 
=  ClientSockFd ;
    FD_SET(ListenSock, 
& AllSockFd);
    FD_SET ReadSockFd;    
// 读集合
    FD_SET WriteSockFd;     // 写集合
     while ( 1 )
    {
        FD_ZERO(
& ReadSockFd);
        FD_ZERO(
& WriteSockFd);
        ReadSockFd 
=  AllSockFd;
        WriteSockFd 
=  AllSockFd;

        
int  nRet  =  select( 0 & ReadSockFd,  & WriteSockFd, NULL, NULL);    
        
if (SOCKET_ERROR  ==  nRet)
        {
            
continue ;
        }
        
// 有请求事件发生
         if  (FD_ISSET(ListenSock,  & ReadSockFd))
        {
            
// 接受请求
            SOCKET ClientSock;
            u_short Port;
            
bool  nRe  =  ( * (Pam.pListenSock)).Accept( & ClientSock,  0 & Port);
            
if (nRe)
            {
                FD_SET(ClientSock, Pam.pClientSockFd);
                
// 设置套接字发送缓冲区80K
                 int  nBuf  =  SOCKET_BUFF;
                
int  nBufLen  =   sizeof (nBuf);
                
int  nRe  =  setsockopt(ClientSock, SOL_SOCKET, SO_SNDBUF, ( char * ) & nBuf, nBufLen);
                
if (SOCKET_ERROR  ==  nRe)
                    AfxMessageBox(
" setsockopt error! " );    
                
// 检查缓冲区是否设置成功
                nRe  =  getsockopt(ClientSock, SOL_SOCKET, SO_SNDBUF, ( char * ) & nBuf,  & nBufLen);
                
if (SOCKET_BUFF  !=  nBuf)
                    AfxMessageBox(
" 检查缓冲区:setsockopt error! " );
                
else
                    AfxMessageBox(
" 已连接客户端! " );
            }
        }
        
// 判断是否可读或可写
         for (u_int n  =   0 ;n  <  ClientSockFd.fd_count;n ++ )
        {
                
if (FD_ISSET(ClientSockFd.fd_array[n],  & ReadSockFd))         // 发现可读
                {        
                        
// 接收数据
                        
// 如果失败 删除此元素        
                }
                
if (FD_ISSET(ClientSockFd.fd_array[n],  & WriteSockFd))     // 发现可写  
                {
                        
// 发送缓冲区未满可以发送
                        
// 如果失败 删除此元素
                }
        }
    }

转载于:https://www.cnblogs.com/yunboy4/archive/2009/08/04/1538915.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值