最近做一个套接字编程的应用,服务器使用Unix。
对于套接字异步的选择,一般有两种模式,一种是对每个新到来的连接都创建一个线程(pthread),可以使用线程池对其进行管理;
另外一种是使用单进程下的异步I/O,通过函数select()来实现;
select()函数可以完成非阻塞方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常
这里的非阻塞是指进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况
如果事件发生则与阻塞方式相同;若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行)
而至于这两者那一种效率更高就比较模糊了。
下面是IBM关于异步服务器的观点:
另一种称为 异步 或 非阻塞 socket 的技术甚至可能比线程化或分支方法更有效率。异步编程背后的概念是将执行保持在单个线程内,但是要轮询每个打开的 socket,以确定它是否有更多的数据在等待读入或写出。然而,非阻塞 socket 实际上仅对受 I/O 约束的进程有用。我们使用sleep()
创建的受 CPU 约束的服务器模拟就在一定程度上遗漏了这个要点。此外,非阻塞 socket 对 TCP 连接比对 UDP 连接更有意义,因为前者保持一个可能仍然具有未决数据的打开连接。
概而言之,异步对等方(客户机 或 服务器)的结构是一个轮询循环 ―― 通常使用函数 select()
或它的某个高级包装,比如 Python 的asyncore
。在每次经过循环时,您都要检查所有打开的 socket,以确定哪些当前是可读的,以及哪些当前是可写的。这检查起来很快,并且您可以简单地忽略当前没有为 I/O 操作做好准备的任何 socket。这种 socket 编程风格避免了与线程或进程相关联的任何开销。
至此,关于两者的选择也比较清楚了。