zoukankan      html  css  js  c++  java
  • Socket Select IO模型

    select技术主要由一个函数和几个宏来提供支持:

    /* 
     * 功能:监视多个文件描述符,直到有一个或多个文件描述符准备好做某种IO操作时返回 
     * 返回:当调用成功时,返回已准备好的文件描述符个数;发生错误时返回-1,可以通过errno得到错误类型 
     * 参数: 
     *      nfds      - 后面三个文件描述符集合中最大的文件描述符加1(想想为什么?) 
     *      readfds   - 等待进行读操作的文件描述符,指针传递,在select返回时会改变这个参数的值,只保留已准备好的文件描述符 
     *      writefds  - 等待进行写操作的文件描述符,指针传递,在select返回时会改变这个参数的值,只保留已准备好的文件描述符 
     *      exceptfds - 监视异常的文件描述符号,很少用到 
     *      timeout   - 程序会在select调用的地方阻塞,你可以通过设置超时让程序可以在一定时间间隔后继续执行 
     
    */ 
    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 
     
    /* 
     * 功能:将指定文件描述符从指定的描述符集合中清除 
     * 参数: 
     *      fd  - 文件描述符 
     *      set - 文件描述符集合 
     
    */ 
    void FD_CLR(int fd, fd_set *set); 
     
    /* 
     * 功能:检查一个文件描述符是否在集合中 
     * 返回:存在时返回非0整数,不存在则返回0 
     * 参数: 
     *      fd  - 文件描述符 
     *      set - 文件描述符集合 
     
    */ 
    int  FD_ISSET(int fd, fd_set *set); 
     
    /* 
     * 功能:设置一个文件描述符到集合中 
     * 参数: 
     *      fd  - 文件描述符 
     *      set - 文件描述符集合 
     
    */ 
    void FD_SET(int fd, fd_set *set); 
     
    /* 
     * 功能:将一个文件描述符集合清零 
     * 参数: 
     *      set - 文件描述符集合 
     
    */ 
    void FD_ZERO(fd_set *set);

     
    下面是select模型的举例:
    代码
     1     SOCKET m_sockSrv = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
     2     if (m_sockSrv == INVALID_SOCKET)
     3      {
     4            cout << "Error: " << WSAGetLastError() << endl;
     5         return false;
     6      }
     7        SOCKADDR_IN addrSrv;
     8        addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
     9        addrSrv.sin_family = AF_INET;
    10       addrSrv.sin_port = htons(nPort);
    11 
    12     int iRet;
    13       iRet = bind(m_sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    14     if (iRet == SOCKET_ERROR)
    15       {
    16              cout << "Bind error! " << WSAGetLastError << endl;
    17         return false;
    18       }
    19 
    20       iRet = listen(m_sockSrv, LISTEN_MAX_LINK);
    21     if (iRet == SOCKET_ERROR)
    22       {
    23             cout << "Listen error! " << WSAGetLastError << endl;
    24         return false;
    25       }
    26 
    27       fd_set fdSocket; //所有的可用套接字集合
    28       FD_ZERO(&fdSocket);
    29       FD_SET(m_sockSrv,&fdSocket);
    30     char buf[1024= {0};
    31     int  nLength = 0;
    32     while(TRUE)
    33       {
    34              fd_set fdRead = fdSocket;
    35         int nRet = ::select(0&fdRead, NULL, NULL, NULL);
    36         if (nRet)
    37           {
    38             for (int i = 0; i < (int)fdSocket.fd_count; i++)
    39                {
    40                 if (FD_ISSET(fdSocket.fd_array[i], &fdRead))
    41                    {
    42                     if (fdSocket.fd_array[i] == m_sockSrv)
    43                            {
    44                       if (fdSocket.fd_count < FD_SETSIZE)
    45                                 {
    46                                       sockaddr_in addrRemote;
    47                               int nAddrLen = sizeof(addrRemote);
    48                                       SOCKET sNew = ::accept(m_sockSrv, (SOCKADDR*)&addrRemote, &nAddrLen);
    49                                       FD_SET(sNew, &fdSocket);
    50                                       TRACE("接收到连接(%s)\n",::inet_ntoa(addrRemote.sin_addr));
    51                                 }
    52                         else
    53                                 {
    54                                       TRACE("连接数太多!");
    55                               continue;
    56                                 }
    57                            }
    58                     else
    59                            {
    60                                 nLength = ::recv(fdSocket.fd_array[i],buf,sizeof(recv_struct),0);//recv_struct为接收结构体            
    61                         if ( nLength > 0)
    62                                 {
    63                               //读取接收缓冲区    
    64 
    65                                 }
    66                         else
    67                                 {
    68                                     ::closesocket(fdSocket.fd_array[i]);
    69                                     FD_CLR(fdSocket.fd_array[i],&fdSocket);
    70                                 }
    71                            }
    72                       }
    73                   }
    74               }
    75            else
    76               {
    77                    printf("Failed select()\n");
    78               break;
    79               }
    80         }
  • 相关阅读:
    LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation]
    LeetCode 15 3Sum [sort] <c++>
    LeetCode 81 Search in Rotated Sorted Array II [binary search] <c++>
    LeetCode 33 Search in Rotated Sorted Array [binary search] <c++>
    LeetCode 80 Remove Duplicates from Sorted Array II [Array/auto] <c++>
    将博客搬至CSDN
    leetcode
    (转载) 图像领域常用资源
    Unity3D 之 C# 脚本
    Kinect 人机交互开发实践
  • 原文地址:https://www.cnblogs.com/pbreak/p/1928968.html
Copyright © 2011-2022 走看看