选择模型2

选择模型

fd_set结构可以把多个套接字连在一起,形成一个套接字集合

typedef struct fd_set{
u_int fd_count;//下面数组的大小
SOCKET fd_array[FD_SETSIZE];//套接字句柄数组
}fd_set;

网络事件:

readfds集合:数据可读,连接关闭,重启或者中断

writefds集合:数据能发送

exceptfds集合:OOB数据可读

设置超时:

如果为null为无限阻塞,知道有网络事件发生

typedef struct timeval{
long tv_sec;//指示等待多少秒
long tv_usec;//指示等待多少毫秒
}timeval;

应用举例

1 初始化fdSocket集合,添加监听套接字句柄

2 将fdSocket集合拷贝fRead传递给select函数,当有事件发生的时候,select函数移除fRead中没有未决IO操作的句柄,然后返回

3 比较原来的fdSocket集合,与select处理过的fdRead集合,确定哪些套接字有未决IO并处理这些IO

4 回到2进行选择

 1 CInitSock theSock;//初始化winsock库
 2 int main()
 3 {
 4     USHORT nPort=4567;//此服务器监听的端口号
 5     //创建监听套接字
 6     SOCKET sListen=::listen(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 7     sockaddr_in sin;
 8     sin.sin_family = AF_INET;
 9     sin.sin_port = htons(nPort);
10     sin.sin_addr.S_un.S_addr = INADDR_ANY;
11     //绑定套接字到本地机器
12     if(::bind(sListen,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR)
13     {
14         printf("Failed bind()!\n");
15         return 0;
16     }
17     //进入监听模式
18     ::listen(sListen,5);
19     
20     //select模型处理过程
21     ////////////////////////////////////////////////////////////////////////////
22     // 1  初始化fdSocket集合,添加监听套接字句柄
23     fd_set fdSocket;//所有可用套接字集合
24     FD_ZERO(&fdSocket);
25     FD_SET(sListen,&fdSocket);
26     while(TRUE)
27     {
28         ////////////////////////////////////////////////////////////////////////
29         //2 将fdSocket集合拷贝fRead传递给select函数,当有事件发生的时候,select函数移除fRead中没有未决IO操作的句柄,然后返回
30         fd_set fdRead = fdSocket;
31         int nRet = ::select(0,&fdRead,NULL,NULL,NULL);
32         if(nRet>0)
33         {
34             ///////////////////////////////////////////////////////////////////
35             // 3  比较原来的fdSocket集合,与select处理过的fdRead集合,确定哪些套接字有未决IO并处理这些IO
36             for(int i=0;i<(int)fdSocket.fd_count;i++)
37             {
38                 if(FD_ISSET(fdSocket.fd_array[i],&fdRead))
39                 {
40                     if(fdSocket.fd_array[i]==sListen)// 1 监听套接字连接新连接
41                     {
42                         sockaddr_in addrRemote;
43                         int nAddrLen = sizeof(addrRemote);
44                         SOCKET sNew = ::accept(sListen,(SOCKADDR*)&addrRemote,&nAddrLen);
45                         FD_SET(sNew,&fdSocket);
46                         printf("接收到连接(%s)\n",::inet_ntoa(addrRemote.sin_addr));
47                     }
48                     else
49                     {
50                         printf("Too much connections!\n");
51                         continue;
52                     }
53                 }
54                 else
55                 {
56                     char szText[256];
57                     int nRecv = ::recv(fdSocket.fd_array[i],szText,strlen(szText),0);
58                     if(nRecv > 0)//可读
59                     {
60                         szText[nRecv] = '\0';
61                         printf("接收到数据:%s\n",szText);
62                     }
63                     else//连接关闭或者重启
64                     {
65                         ::closesocket(fdSocket.fd_array[i]);
66                         FD_CLR(fdSocket.fd_array[i],&fdSocket);
67                     }
68                 }
69             }
70         }
71         else
72         {
73             printf("Failed select()!\n");
74             break;
75         }
76     }
77     return 0;
78 }

 

 

posted @ 2012-10-10 23:48 xingoo 阅读(...) 评论(...) 编辑 收藏