设想一个场景,用socket连接建立后,使用read来读取传来的所有数据直到对方close掉连接描述符,发来FIN包,如果使用非阻塞模型,写法是这样的
while( read(fd, buf, n) != EOF );
这样需要用where循环不断判断是否读完,读完才能推出循环,这虽然是同步非阻塞NIO模型但是不能发挥真实的威力。
真正能发挥NIO威力的是使用IO多路复用 + 同步非阻塞IO
比如使用一个阻塞的select/poll/epoll来监听read是否有新的数据到来,此时epoll要设置为水平触发(LT),select和poll默认都是LT的。
伪代码:
while(true) {
阻塞等待fd1,fd2可读性// 阻塞的IO多路复用模型,需要使用非阻塞IO
read(fd1) // 非阻塞,可能需要读一部分
read(fd2) // 非阻塞,可能需要读一部分
}
拓展:
水平触发LT:每当有数据到来都要进行触发,比方说来了一条数据就要进行触发,或者是可写一条数据,这里的“一条”的大小按不同操作系统可能略有不同,但基本是指1B
边缘触发ET:只有当状态发生改变才能出发,比如read一开始无法读,当可以读了就出发了,这时候需要一口气把数据读完,所以需要搭配异步IO或者是多线程/多进程模型。
PS:阻塞还会带来进程切换,有额外的开销