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

介绍WinSock中“阻塞”与“非阻塞”的概念。

2013年09月14日 ⁄ 综合 ⁄ 共 1738字 ⁄ 字号 评论关闭
在Windows环境下,一般采用“非阻塞”方式。对于客户端Socket来说,如果把Cli
entType特性设为ctNonBlocking,表示采用非阻塞方式进行连接。当位于另一端的服务
器端Socket试图进行读或写时,客户端Socket就会得到通知(OnRead事件或OnWrite事件
)。
    对于服务器端Socket来说,如果把ServerType特性设为stNonBlocking,表示采用非
阻塞方式进行连接。当位于另一端的客户端Socket试图进行读或写时,服务器端Socket
就会得到通知(OnClientRead事件或OnClientWrite事件)。在响应这些事件的句柄中都有
一个Socket参数,这个参数很有用,它就是服务器端或客户端的Socket对象(TClientWi
nSocket或TServerWinSocket或TServerClientWinSocket),这些Socket对象的共同基类
是TCustomWinSocket,TCustomWinSocket提供了在Internet上传输数据的方法,例如,
要读取数据,可以调用ReceiveBuf或ReceiveText,要发送数据,可以调用SendBuf、Se
ndStream、SendText或SendStreamThenDrop,其中,SendStreamThenDrop能够在发送完
数据后自动断开Socket的连接。SendStream和SendStreamThenDrop适合于发送流对象,
例如文件,不过,您并不需要显式地删除流对象,因为当Socket之间的连接断开时,So
cket会自动释放所有的流对象。
    与“非阻塞”方式不同的是,在“阻塞”方式下没有诸如OnRead或OnWrite等异步事
件,Socket必须主动去读或写数据,在读或写操作完成之前,应用程序处于等待状态,
这样就不可避免地会影响整个应用程序的性能。
    对于客户端Socket来说,如果把ClientType特性设为ctBlocking,表示采用阻塞方
式进行连接。为了尽可能地减少“阻塞”方式的副作用,您可以把所有涉及到读写的操
作放在一个单独的线程中,这样,在32位的Windows环境下其它线程能够继续得到执行。
当然,如果在读写函数中客户程序本身没有其它事情要做,您就不必创建一个线程了。

    对于服务器端Socket来说,如果把ServerType特性设为stThreadBlocking,表示采
用阻塞方式进行连接,C++ Builder 3为每一个阻塞方式的连接自动分配一个新的线程,
这样,即使有某个客户正在进行读写操作,其它客户也不必等待。服务器端的Socket用
TServerClientThread对象来操纵每一个线程,当线程开始执行时,它就检查位于另一端
的客户是否正在试图进行写,如是,就触发OnClientRead事件,如果检查出客户不在试
图写,它就触发OnClientWrite事件让服务器去写。
    实际上,这种用线程对象来管理连接的方式可以认为是“假阻塞”方式,就编程而
言,与“非阻塞”方式是相似的。比较麻烦的是客户端,它怎么知道对方(指服务器端)
已准备好读或写呢?这就要用到TWinSocketStream对象,调用这个对象的WaitForData可
以保证服务器和客户的同步。用TWinSocketStream对象进行读或写时,如果在20秒内操
作还没有完成,TWinSocketStream对象就认为超时了,它就会自动断开连接,这样就能
避免应用程序锁死。正是由于TWinSocketStream对象具有超时保护机制,您也可以把TW
inSocketStream对象用于服务器端进行读或写。要注意的是,TWinSocketStream对象不
能用于“非阻塞”方式。
    也许有的读者要问,既然阻塞方式可能会影响应用程序的性能,虽然用多线程技术
可以加以弥补,但又使编程变得复杂,为什么还要用“阻塞”方式呢?这是因为,在阻
塞方式下,读或写是主动的,您可以在读或写操作完成后安全地关闭Socket的连接。而
在“非阻塞”方式下,读或写是随机的,Socket必须经常保持在连接状态才能捕捉到异
步事件。

来源于网络!

抱歉!评论已关闭.