非阻塞IO
非阻塞IO在套接字对象上提供了一个选项Non_Blocking,当这个选项打开时,读写方法不会阻塞,而是能读多少读多少,能写多少写多少.至于能都多少取决于内核为套接字分配的读缓冲区内部的数据字节数,能写多少取决于内核为套接字分配的写缓冲区的空闲空间字节数.读写方法都会通过返回值来告知程序实际读写了多少字节.
阻塞和非阻塞区别
阻塞
当我们调用socket读写方法,默认他们是阻塞的,比如read方法要传递一个参数n,表示读取多少字节后返回,如果没有读够线程会卡在那里,直到新的数据到来或者连接关闭,read方法才可以返回,线程才能继续处理.
非阻塞
根据socket分配的缓冲区数据字节数能读多少读多少,通过返回值告知程序读了多少字节
事件轮询(多路复用)
非阻塞IO有个问题,那就是线程要读数据,结果读了一部分就返回了,线程如何知道何时才应该继续读.也就是当数据到来时,线程如何得到通知.写也是一样,如果缓冲区满了,写不完,剩下的数据何时才能继续写,线程也应该得到通知.
事件轮询api
最简单的事件轮询api是select函数,他是操作系统提供给用户程序的api.输入读写描述符列表read_fds & write_fds,输出与之对应的可读可写事件.同时还提供了一个timeout参数,如果没有任何事件到来,那么就是最多等待timeout时间,线程处于阻塞状态. 一旦期间有任何事件到来,就可以立即返回.时间了之后还是没有任何事件到来也会立即返回.拿到事件后,线程就可以继续挨个处理相应的事件.处理完了继续过来轮询.于是线程就进入了一个死循环,我们把这个死循环称为事件循环,一个循环为一个周期.