现在的位置: 首页 > 综合 > 正文

套接字模式

2013年04月24日 ⁄ 综合 ⁄ 共 1530字 ⁄ 字号 评论关闭

   1.同步I/O和异步I/O

CPU执行代码(当前活动线程)时遇上一个I/O请求(例如调用ReadFile/WriteFilerecv/send)时,系统产生一个中断,当前活动线程阻塞在此,让CPU去完成这个I/O请求,等到完成后,系统再次产生一个中断让原先的程序继续运行。也就说通过中断保持这两者间的同步。可以将终端理解为硬件化的信号量。

 

这就是所谓的同步I/O,一个线程中只可能同时处理一个I/O请求。因为一个I/O操作是非常耗时的,所以代码挂起后等待I/O完成的这段时间内,这个线程浪费了很多个指令周期。如果要同时反复读写大文件,则同步I/O的效率是很低的。

 

当然,可以考虑使用多线程来处理。例如在设计服务器时可以使用多线程来处理客户请求,每有一个客户连接请求,就创建一个新线程,专门处理它的通信请求。对于小型服务器来说,这不是问题。对于同时处理成千上万个请求的大型服务器而言,使用多线程是无效的,因为系统能够支持的线程数量毕竟是有限制的。另外一种解决方案就是使用共享负载的线程池,这涉及到异步I/O

 

在异步I/O中,当CPU执行你的代码遇上一个I/O请求时,使用一个线程去处理I/O请求,并且当前调用线程并不挂起。如果后续代码和这个I/O有关(例如需要等待I/O操作的结果),那么它就要等到这个I/O操作完成。通常在一个线程中调用WaitForSingleObject/WaitForMultipleObjectsWSAWaitForMultipleEvents(WSA)GetOverlappedResult等函数就可以得到I/O完成的消息,然后再对数据进行处理。但如果后续的代码和这个I/O操作无关,你就可以以更快的速度执行下去了,而无需等待I/O请求的完成了。这就是异步I/O了。

 

 据此,套接字有锁定和非锁定两种模式。

 

2.套接字的两种模式

   (1)锁定模式套接字

对于锁定模式的套接字而言,调用任何一个Winsock API函数(accept/recv/send)都会耗费或长或短的时间“等待”返回。大多数Winsock应用都是遵照一种“生产者-消费者”模型来编制。在这种模型中,应用程序需要读取(或写入)指定数量的字节,然后以在对读取的数据执行一些计算。

在应用程序中,可以为每个套接字都创建一个负责读取网络数据的读线程(ReadThread),以及一个负责对数据执行计算德数据处理线程(ProcessThread)。尽管这会增大一些开销,但的确是一种可行的方案。缺点便是扩展性极差,而且无法应对大规模的通信情况。

(2)非锁定模式套接字

将一个套接字置为非锁定模式之后,Winsock API调用会立即返回。大多数情况下,这些

调用都会“失败”,并返回一个WSAEWOULDBLOCK错误。它意味着请求的操作在调用期间没有时间完成。举个例子来说,假如在系统的输入缓冲区中,尚不存在“待决”的数据,那么recv(接收数据)调用就会返回WSAEWOULDBLOCK错误。通常,我们需要重复调用同一个函数,直至获得一个成功返回代码。

假如需要编写更多的代码,以便在每个 Winsock调用中,对收到一个WSAEWOULDBLOCK错误的可能性加以应付,那么非锁定套接字便显得有些难于操作。在这些情况下,可考虑使用“套接字I/O模型”,它有助于应用程序通过一种异步方式,同时对一个或多个套接字上进行的通信加以管理。

 

参考

Windows 2000 Systems Programming Black Book  Al Williams

Network Programming for Microsoft Windows  Anthony Jones,Jim Ohlund

 

 

抱歉!评论已关闭.