Winsock—I/O模型之选择模型(一)

 Winsock中提供了一些I/O模型帮助应用程序以异步方式在一个或多个套接字上管理I/O。

  这样的I/O模型有六种:阻塞(blocking)模型,选择(select)模型,WSAAsyncSelect模型,WSAEventSelect模型,重叠(overlapped)模型,完成端口(completion port)模型。

  选择模型:

  目的:允许想要避免在套接字调用上阻塞的应用程序有能力管理多个套接字。

  一、select函数
             select函数可以确定一个或者多个套接字的状态。如果套接字上没有网络事件发生,便进入等待状态,以便执行同步I/O。

1   int select(int nfds,         //仅是为了与套接字兼容,忽略
2     fd_set* readfds,         //指向一个套接字集合,检查其可读性
3     fd_set* writefds,         //检查一个套接字集合,检查其可写性
4     fd_set* exceptfds       //指向一个套接字集合,检查错误
5     const struct timeval* timeout    //指定函数最长等待时间,如果为NULL,则等待时间为无限长
6 );  

  函数调用成功,返回发生网络事件的所有的套接字数量的总和。如果超过了时间限制,返回0,失败则返回SOCKET_ERROR。

  1、套接字集合
        fd_set结构可以把多个套接字连接在一起,形成一个套接字集合。select函数可以测试这个集合中哪些套接字有事件发生。

    WINSOCK2.h中的定义如下:

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

    WINSOCK中定义的4个操作fd_set套接字集合的宏:

1     FD_ZERO(*set);     //初始化set为空集合。集合使用前应该总是清空。
2     FD_CLR(s,*set);    //从set移除套接字s
3     FD_ISSET(s,*set)    //检查s是不是set的成员,如果是返回TRUE.
4     FD_SET(s,*set)     //添加套接字到集合

   2、设置超时
       最后的参数timeout是timeval结构的指针,它指定了select函数等待的最长的时间。如果设为NULL,select将会无限阻塞,直到有网络事件发生。

    timeval结构定义如下:

1  typedef struct timeval
2 {
3      long tv_sec;      //指示等待多少秒
4      long tv_usec;     //指示等待多少毫秒
5 }timeval;

  服务器端代码:

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

Winsock—I/O模型之选择模型(一)的相关文章

异步I/O:选择模型(select)

摘自:www.cctry.com 选择模型selectint select( __in int nfds, 参数nfds会被忽略.之所以仍然要提供这个参数,只是为了保持与Berkeley套接字兼容. __in_out fd_set* readfds, 用于检查可读性 __in_out fd_set* writefds, 用于检查可写性 __in_out fd_set* exceptfds, 用于检查例外数据 __in const struct timeval* timeout 时间结构); fd

一.Windows I/O模型之选择(select)模型

1.选择(select)模型:选择模型:通过一个fd_set集合管理套接字,在满足套接字需求后,通知套接字.让套接字进行工作.避免套接字进入阻塞模式,进行无谓的等待.选择模型的核心的FD_SET集合和select函数.通过该函数,我们可以们判断套接字上是否存在数据,或者能否向一个套接字写入数据. 2.select函数:int select(    int nfds,//忽略,只是为了兼容而存在.    fd_set FAR* readfds,//可读性检查(有数据可读入,连接关闭,重设,终止) 

ExtJS表格——行号、复选框、选择模型

本篇的内容是为表格添加行号,和复选框,最后谈一下Ext的选择模型.内容比较简单,就直接上代码了.一. 设置行号   行号的设置主要问题在于删除某一行后需要重新计算行号  Ext.onReady(function() {         var cm = new Ext.grid.ColumnModel([                     new Ext.grid.RowNumberer(),           --在这里设置行号                    { header:

巧克力项目之生命周期模型的选择

3月8日会议记录       会议记录者:李宁 今天,我们小组就老师布置的关于巧克力项目的生命周期模型进行了讨论.我们的讨论根据的是书上关于各种生命周期模型对比的表格,上面列举的每一种方法都讨论了是否符合我们小组的开发,进过筛选最终选定了迭代--递增生命周期模型.选择迭代--递增模型的原因是:迭代--递增模型更接近于现实中的开发模型,可以在每一个版本的基础上,继续升级跟新,符合我们开发的原则,同时适用于我们小组的开发水平.至于其他模型没有选择的原因,下面将一一列举.编码--修补模型和瀑布模型,是

模型评估与模型选择

机器学习算法 原理.实现与实战——模型评估与模型选择 1. 训练误差与测试误差 机器学习的目的是使学习到的模型不仅对已知数据而且对未知数据都能有很好的预测能力. 假设学习到的模型是$Y = \hat{f}(X)$,训练误差是模型$Y = \hat{f}(X)$关于训练数据集的平均损失: $$R_{emp}(\hat{f}) = \frac{1}{N}\sum_{i=1}^NL(y_i,\hat{f}(x_i))$$ 其中$N$是训练样本容量. 测试误差是模型$Y = \hat{f}(X)$关于测

机器学习之模型评估与模型选择(学习笔记)

时间:2014.06.26 地点:基地 -------------------------------------------------------------------------------------- 一.训练误差和测试误差 机器学习或者说统计学习的目的就是使学习到的模型不仅对已知数据而且对未知数据都都很好的预测能力.不同的学习方法会得出不同的模型.在评判学习方法的好坏时,常用的是: 1.基于损失函数的模型的训练误差                          2.模型的测试误

机器学习如何选择模型 &amp; 机器学习与数据挖掘区别 &amp; 深度学习科普

今天看到这篇文章里面提到如何选择模型,觉得非常好,单独写在这里. 更多的机器学习实战可以看这篇文章:http://www.cnblogs.com/charlesblc/p/6159187.html 另外关于机器学习与数据挖掘的区别, 参考这篇文章:https://www.zhihu.com/question/30557267 数据挖掘:也就是data mining,是一个很宽泛的概念.字面意思就是从成吨的数据里面挖掘有用的信息.这个工作BI(商业智能)可以做,数据分析可以做,甚至市场运营也可以做

利用MEGA-X选择模型及构建美化进化树

对于经常构建进化树的朋友来说,MEGA应该是个老朋友了.MEGA从1993年的第一个版本问世一直锤炼到去年刚刚发布的MEGA-X,已经经历了26年,在这期间,MEGA共更新八个版本,先后在Molecular Biology and Evolution.Bioinformatics.Computer Applications in the Biosciences等期刊上发表共十篇论文,总引用量已经超过11万.对于如此熟悉的一个老朋友,让我们今天一起来了解一下它的新版本MEGA-X,开发它更多的使用

Winsock IO模型之IOCP模型

http://blog.csdn.net/lostyears/article/details/7436802 Windows平台上伸缩性最好的一种I/O模型莫过IOCP了,不过设计和实现起来比较复杂一些.针对成千上万个套接字的并发处理,IOCP采用了线程池+队列+重叠结构的内核机制完成任务.需要说明的是IOCP其实不仅可以接受套接字对象句柄,还可以接受文件对象句柄等. 为避免线程上下文切换,它采用了线程池.除此之外,在基于事件模型或重叠模型中不得不遇到WSAWaitForMultipleEven