创建一个能用的SOCKET是非常简单的,GLIBC已经为你做了很多简化工作,但是从另一个角度来说,一个通用的SOCKET不代表一个高效性能的网络应用.我们前面说到sockfd其实同真正的FD是一样的.都是LINUX下的一个打开的设备描述符.内核通过这个描述符进行I/O操作.进行I/O操作就有一个性能问题,这个性能问题在于两个条件,一个条件是对同一个FD,有多个客户进行操作时如何更好的排队.另一个就是一个客户如果有多个FD,那应该怎么排队选择问题.我们知道不管是READ还是READFREOM它其实都是阻塞操作.一旦占用就始终等到有新数据来到.那么如何解决这个问题呢?我们看第一个排队问题,就是多个客户使用同一个SOCKET,如果当前来的数据不是占据的客户,那显然会导致阻塞.我们想出另一个方法,就是当一个或多个I/O条件满足,如输入数据已准备好被读或者描述字可以承接更多输出时的时候,作为消费者的客户端可以被通知到,这样的能力称之为I/O复用.这个在GLIBC中设计了两个新的函数就是SELECT/POLL.以下是几种I/O模型的比较图: 1)阻塞I/O模型,缺省的套接口都是阻塞的,你使用READ时一定要有数据时进程才会进行下去.如下图: 2)非阻塞I/O,在将套接口设置为非阻塞方式下,内核就让请求的I/O操作在没有数据的情况直接返回一个错误,不再等特.显然这种操作需要不停的尝试,消耗非常多的CPU. 非阻塞I/O可以使用fcntl参数进行设置READ/RECVFROM,但很明显它的尝试次数非常多. [windriver@windriver-machine ltest]$ gcc noread.c -o noread [windriver@windriver-machine ltest]$ strace -e read -o out.txt ./noread aaa aaa bbbbb bbbbb ccccc ccccc [windriver@windriver-machine ltest]$ cat out.txt read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\20"..., 512) = 512 read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, "aaa\n", 4096) = 4 read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, "bbbbb\n", 4096) = 6 read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, "ccccc\n", 4096) = 6 read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, "\n", 4096) = 1 read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 4096) = -1 EAGAIN (Resource temporarily unavailable) read(0, 0x80498c0, 409 |