• 套接字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))    //发现可写  
                    {
                            
    //发送缓冲区未满可以发送
                            
    //如果失败 删除此元素
                    }
            }
        }

    兴趣是学习的动力。
  • 相关阅读:
    英飞凌TLE9461V33 SBC芯片
    Lin总线诊断级别定义 CLASS I 、II 、III
    AUTOSAR_SWS_CANInterface 阅读
    AUTOSAR_SWS_CANTransceiverDriver 阅读
    VS2013 快捷键
    Can总线空闲状态时候,TX,RX电平
    postman
    题目2
    Robot Framework 自动化测试
    银行测试 http://blog.csdn.net/stillming/article/details/42275251
  • 原文地址:https://www.cnblogs.com/yunboy4/p/1538915.html
Copyright © 2020-2023  润新知