织梦CMS - 轻松建站从此开始!

罗索

select()* 执行同步I/O多路复用

jackyhwei 发布于 2010-10-14 13:33 点击:次 
select()* 执行同步I/O多路复用。 select函数的参数( int nfds, fd_set readfds, fd_set writefds, fd_set exceptfds, const struct timeval timeout )
TAG:

select函数的参数

( int nfds, fd_set readfds, fd_set writefds, fd_set exceptfds, const struct timeval timeout )

我记得是:第一个是个较为次要的值,设成0就行了。
后面的几个FD_SET类型的参数才是最重要的;
第一个FD_SET型的参数readfds是表示要被检查是否可读的 Sockets,把你想要接收数据的那个套接字放在这里;
第二个FD_SET参数ritefds是表示要被检查是否可写的 Sockets,将你要发送数据的套接字放在这里;
还有个FD_SET参数exceptfds是表示要被检查是否有错误的 Sockets
select() 函式的第五个参数timeout,是让我们用来设定 select 函数要等
待(block)多久。兹述说如下:

(1)如果 timeout 设为「NULL」,那么 select() 就会一直等到「至少」某
一个 socket 的事件成立了才会 return,这和其他的 blocking 函数一样。

select( ..., NULL ) /* blocking */

(2)如果 timeout 的值设为 {0, 0} (秒, 微秒),那么 select() 在检查后,不管有没有 socket 的事件成立,都会马上 return,而不会停留。

timeout.tv_sec = timeout.tv_usec = 0;
select( ..., &timeout ) /* non-blocking */

(3)如果 timout 设为 {m, n},那么就会等到至少某一个 socket 的事件发生,或是时间到了(m 秒 n 微秒),才会 return。

timeout.tv_sec = m;
timeout.tv_usec = n;
select( ..., &timeout ) /* wait m secconds n microseconds */

返回值: 成功 - 符合条件的 Sockets 总数 (若 Timeout 发生,则为 0)
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)

说明: 使用者可利用此函式来检查 Sockets 是否有资料可被读取,或是有空间可以写入,或是有错误发生。

关于对FD_SET类型的操作,有几个比较重要的宏:
FD_ZERO(*set) -- 将 set 的值清乾净
FD_SET(s, *set) -- 将 s 加到 set 中
FD_CLR(s, *set) -- 将 s 从 set 中删除
FD_ISSET(s, *set) -- 检查 s 是否存在於 set 中

参数 readfds、writefds、及 exceptfds 都是 「called by value-result」;而「called by value-result」的意思就是说,我们在将参数传给系统时,要先设启始值,并将这些参数的位址(address)告诉系统;而系统则会利用到这些值来做些运算或其他用途,最后并将结果再写回这些参数的位址中。
因此这些参数的值在传入前和函数返回后,可能会不同;所以每次调用select() 前,对这些参数一定要重新设定它们的值。

假设我们要检查 socket 1 和 2 目前是否可以用来传送资料,以及 socket 3 是否有资料可读;我们不打算检查 sockets 是否有错误发生,所以 exceptfds 设为NULL。步骤大致如下:

FD_ZERO( &writefds ); /* 清除 writefds */
FD_ZERO( &readfds ); /* 清除 readfds */
FD_SET( 1, &writefds ); /* 将 socket 1 加到 writefds */
FD_SET( 2, &writefds ); /* 将 socket 2 加到 writefds */
FD_SET( 3, &readfds ); /* 将 socket 3 加到 readfds */
select( ..., &readfds, &writefds, NULL, ...) /* 调用 select() 来检查事件 */
if (FD_ISSET( 1, &writefds )) /* 检查 socket 1 是否可写 */
send( 1, data ); /* 调用 send() 一定成功 */
if (FD_ISSET( 2, &writefds )) /* 检查 socket 2 是否可写 */
send( 2, data ); /* 调用 send() 一定成功 */
if (FD_ISSET( 3, &readfds )) /* 检查 socket 2 是否可读 */
recv( 3, data ); /* 调用 recv() 一定成功 */

不知道说得清不清楚?你明白了没有?  

(jacky)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201010/10301.html]
本文出处:百度博客 作者:jacky
顶一下
(2)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容