IO多路复用是否会遗漏IO事件?

这个问题如果完整贴代码可能会比较长,所以只简单说一下。
Test1是一个简单的成功的例子:
server端代码大概如下:

set up a listenfd
while (1) {
    if (select(listenfd) > 0) {
        if (FD_ISSET(listenfd)) {
            accept new clientfd
            read clientfd
            write clientfd
            close clientfd
        }
    }
}

client端代码大概如下:

while (1) {
    set up a clientfd
    write something to server
    read something from server
    output them to console
}

这里是没什么问题的,两个进程无限跑。client会先sleep1秒,等一下server。

Test2改成下面这种更加复杂一点的模式时就卡住了,先看代码:
server端:

set up a listenfd
while (1) {
    if (select(readset, writeset) > 0) {
        foreach(fd in readset) {
            if (fd == listenfd) {
                accept new clientfd
                add clientfd to readset
            } else {
                /*this is a clientfd accepted before*/
                read fd
                remove fd from readset
                add fd to writeset
            }
        }
        foreach(fd in writeset) {
            /*this is a clientfd accepted and readed before*/
            write fd
            remove fd from writeset
            close fd
        }
    }
}

client端:

while (1) {
    set up a clientfd
    write something to server
    read something from server
    output them to console
}
//exactly same as before

client端没有改动,server端将accept之后的动作分开重新交给select去监听。
程序运行的时候是卡住的,我调式也一直卡在select处。
我推测是server端的listenfd在accept到一个clientfd,将该clientfd加入readset的这一过程中,
client端中的fd已经read结束了,因此server端select没有监听到该事件,然后client端在等待server的write,而server在等待client的read?
完整代码地址:
https://github.com/zhaochenyou/tips/blob/master/c/socket/server/select.c

阅读 3.3k
1 个回答

select不指定超时时间?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题