【转载】socket select模型

由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续。

如果想改变这种一直等下去的焦急状态,可以多线程来实现(不再等待,同时去recv,同时阻塞,呵呵),每个socket连接使用一个线程,这样效率十分低下,根本不可能应对负荷较大的情况(是啊,占用各种资源,电脑啊,你耗不起)。

这时候我们便可以采取select模型。

select允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或多个时间发生或经历一段指定时间后才唤醒它。select告诉内核对哪些描述子感兴趣以及等待多长时间。这就是所谓的非阻塞模型,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高。

select的函数原型:

int select
(
     int nfds, //Winsock中此参数无意义
     fd_set* readfds, //进行可读检测的Socket
     fd_set* writefds, //进行可写检测的Socket
     fd_set* exceptfds, //进行异常检测的Socket
     const struct timeval* timeout //非阻塞模式中设置最大等待时间
 )
/*参数列表
int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。
  
fd_set *readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。
  
fd_set *writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。
  
fd_set *errorfds同上面两个参数的意图,用来监视文件错误异常。
  
struct timeval* timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态:
第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;
第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;
第三,timeout的值大于0,这就是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。
*/
/*
返回值:
负值:select错误
正值:某些文件可读写或出错
0:等待超时,没有可读写或错误的文件
*/
第二种解释版本:

参数解释:

参数1 nfds:这个参数是一个被忽略的参数,我们在程序中传入0即可,其目的是与伯克利套接字兼容。

参数2 readfds:可读性监视集合,可读性指有连接到来、有数据到来、连接已关闭、重置或终止。

参数3 writefds:可写性监视集合,可写性指数据可以发送、连接可以成功。

参数4 exceptfds:例外性监视集合,例外性指连接会失败、外带数据到来

参数4 timeout:该参数指定select会等待的时间,者结构很简单,要是有兴趣可以看看msdn

注意:select参数中的三个监视集合至少有一个不能为空,任何其它两个都可为空

fd_set的结构,这个结构是用来装SOCKET的,把要监视SOCKET传给这个结构,然后同select函数进行监视。

struct fd_set
{
  u_int    fd_count;       // how many are SET?
  SOCKET   fd_array[FD_SETSIZE];     // an array of SOCKETs
} ;

和select模型紧密结合的四个宏:

FD_CLR( s,*set) 从队列set删除句柄s。

FD_ISSET( s, *set) 检查句柄s是否存在与队列set中。

FD_SET( s,*set )把句柄s添加到队列set中。

FD_ZERO( *set ) 把set队列初始化成空队列。

select选择模式倚赖于select函数,其思想就是让select函数对传入fd_set进行监视(fd_set中装有你的SOCKET句柄),如果没什么事发生select就将fd_set中的SOCKET清除。

如:

timeval outTime;
outTime.tv = 1;   //设置等待时间为1s
outTime.usec = 0; //毫秒
fd_set fdread;
while(true)
{
   FD_ZERO(&fdread);
   FD_SET(sessionSock, &fdread) //sessionSock为之前创建的会话套接字
   select(0, &fdread, NULL, NULL, &outTime);
   if(FD_ISSET(sessionSock, &fdread))//判断套接字是否还在集合中
   {
      recv_cnt = recv(sessionSock, buf, bufSize, 0);
   }
   else
   {
      //没有数据写入,进行其他操作
   }
}
时间: 2024-10-20 18:07:07

【转载】socket select模型的相关文章

socket select()模型

转载:http://www.cnblogs.com/xiangshancuizhu/archive/2012/10/05/2711882.html 由于socket recv()方法是阻塞式的,当有多个客户端连接服务器时,其中一个socket的recv调用产生了阻塞,使其他链接不能继续.如果想改变这种一直等下去的焦急状态,可以多线程来实现(不再等待,同时去recv,同时阻塞),每个socket连接使用一个线程,这样效率十分低下,根本不可能应对负荷较大的情况(是啊,占用各种资源,电脑啊,你耗不起)

socket select模型

由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不再等待,同时去recv,同时阻塞),每个socket连接使用一个线程,这样效率十分低下,根本不可能应对负荷较大的情况(是啊,占用各种资源,电脑啊,你耗不起). 这时候我们便可以采取select模型.select允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或多个事件发生或经历一段指定时间

u3d局域网游戏网络(c# socket select 模型)

之前写了一篇. 发完之后第二天实际应用到游戏之后还是发现了一些小毛病. 比如网络模块有重复使用(多对象)的情况.所以将静态类该成了普通类. 比如安卓下会有些异常出现导致游戏逻辑不正常.所以网络相关的函数有些加了try块. 然后发现写入固定ip的方式根本不适合局域网.于是加了udp做的广播系统,用以服务器和客户端查找ip. udp广播部分和tcp不一样.因为没有连接,所以socket不需要shutdown.我在这里吃了一亏才知道. 别的没什么修改.贴上修正和扩展之后的代码. 有缘之人自取.唯一要求

u3d局域网游戏网络(c# socket select 模型)——续

原文:http://www.cnblogs.com/saucerman/p/5555793.html 因为项目要加语音.语音数据都非常大.所以顺带就把之前写的网络模块一起测试了. 然后发现了一些bug,逐修.本来想在原文上面直接修改掉.但是恐怕已经看到的人拿去用了之后,再回头看也不一定能看明白,索性再写一文,将新文件直接放上来. 错误修改: 网络接收数据后,有一种情况没有处理完整,导致接收数据之后数据池的计数器没有向后偏移 网络数据处理后,当当前包仅剩1字节,下一个次数据进来的时候,需要2字节才

c# socket select 模型代码(u3d)

其实写过多次网络链接.但是因为换了工作,又没电脑在身边,所以以前的代码都没办法翻出来用. 所以从今天起,一些常用的代码只好放到网上. 公司有一个局域网的游戏.本来想用u3d的rpc就可以完成.但是后来说要传语音.于是只要写一个tcp. 先给出服务器和客户端的socket代码段.其他依赖的一些文件,就不贴了. 目前完成的模块大的说就两块,网络和消息分发. 网络部分服务器有玩家池的管理. 网络部分没有想得很详细.因为是局域网,所以也不存在多大开销.如果有需要上千的需求,可能还要优化下代码结构以及锁.

C# Socket select模型

http://www.cnblogs.com/Clingingboy/archive/2011/07/04/2097806.html http://www.cnblogs.com/RascallySnake/archive/2013/07/11/3185071.html http://www.cnblogs.com/ggzss/archive/2011/08/25/2153746.html http://blog.csdn.net/a497785609/article/details/12871

[00020]-[2015-09-18]-[00]-[Windows Socket Select 模型]

int select( int nfds; fd_set FAR* readfds; fd_set FAR* writefds; fd_set FAR* exceptfds; const struct timeval FAR* timeout; ); #define FD_SETSIZE 64typedef struct fd_set{ u_int fd_count; SOCKET fd_array[FD_SETSIZE];}fd_set; struct timeval{ long tv_sec

socket编程:多路复用之select模型

系统提供select函数来实现多路复用输入/输出模型. select函数让我们的程序监视多个文件描述符的状态变化.程序会停在select这里等待,直到被监视的文件描述符中有一个或多个发生了状态变化 函数原型如下: 返回值:   成功返回就绪描述符的个数,超过timeout时间且没有任何事件发生返回0,失败返回-1 参数解释: nfds:    被监视的文件描述符中值最大描述符值加1(描述符是从0开始的,描述符0.1.2...nfds-1均将被测试) 下面三个参数readset.writeset和

windows socket编程select模型使用

int select( int nfds,            //忽略 fd_ser* readfds,    //指向一个套接字集合,用来检测其可读性 fd_set* writefds,   // 指向一个套接字结合,用来检测其可写性 fd_ser* exceptfds, //指向一个套接字集合,用来检测错误 const struct timeval * timeout   //指定此函数等待的最长时间,如果为NULL,则最长时间为无限大. ); 参数说明: (1)   nfds  win