SOCKET通信时,阻塞模式和非阻塞问题?(100)

D

dhszxh

Unregistered / Unconfirmed
GUEST, unregistred user!
SOCKET通信时,阻塞模式和非阻塞到底有什么不同,分别用语哪些场合,两种模式在编码时应该注意些什么?谁能详细讲讲或发个链接资料也可以,先谢谢了!
 

地质灾害

Unregistered / Unconfirmed
GUEST, unregistred user!
http://2ccc.com/article.asp?articleid=492
 
B

bdmh

Unregistered / Unconfirmed
GUEST, unregistred user!
阻塞,要等数据返回才会继续,有假死现象非阻塞想法有点类似 SendMessage和PostMessage的区别
 
4

41426277

Unregistered / Unconfirmed
GUEST, unregistred user!
同步,阻塞有金钱100,20,100,20。。。的面值,就是我一张,你一张,我一张,你一张,。。。异步,非阻塞有金钱100,20,100,20。。。的面值,我先抢完100的,你慢慢拿20吧。
 

虞韩

Unregistered / Unconfirmed
GUEST, unregistred user!
http://www.javaeye.com/wiki/topic/670841
 
J

JC不懂

Unregistered / Unconfirmed
GUEST, unregistred user!
来自:41426277, 时间:2010-6-3 8:03:14, ID:3994424同步,阻塞有金钱100,20,100,20。。。的面值,就是我一张,你一张,我一张,你一张,。。。异步,非阻塞有金钱100,20,100,20。。。的面值,我先抢完100的,你慢慢拿20吧。 很精辟~~
 
M

mxymxy

Unregistered / Unconfirmed
GUEST, unregistred user!
同步=阻塞,就是读取/写入信息的函数如果未成功就会让windos挂起线程,直到有数据可读/有空间可写,完成操作,函数返回。异步=非阻塞,就是收发信息的函数如果有数据可读/有空间可写,完成操作,函数返回。否则函数返回SOCKET_ERROR,错误名为WSAEWOULDBLOCK意即“操作失败”。无论成功与失败,函数立即返回,线程永远不会挂起。正如bdmh所说,有点类似 SendMessage和PostMessage的区别影响到的函数有WSASend,send,recv,WSARecv,accept,WSAAccept等
 
M

mxymxy

Unregistered / Unconfirmed
GUEST, unregistred user!
WINDOWS网络编程技术8章中说道8.1 套接字模式就像我们前面提到的那样, Wi n d o w s套接字在两种模式下执行I / O操作:锁定和非锁定。在锁定模式下,在I / O操作完成前,执行操作的Wi n s o c k函数(比如s e n d和r e c v)会一直等候下去,不会立即返回程序(将控制权交还给程序)。而在非锁定模式下, Wi n s o c k函数无论如何都会立即返回。在Windows CE和Windows 95(安装Winsock 1)平台上运行的应用程序仅支持极少的I / O模型,所以我们必须采取一些适当的步骤,让锁定和非锁定套接字能够满足各种场合的要求。8.1.1 锁定模式对于处在锁定模式的套接字,我们必须多加留意,因为在一个锁定套接字上调用任何一个Winsock API函数,都会产生相同的后果—耗费或长或短的时间“等待”。大多数Wi n s o c k应用都是遵照一种“生产者-消费者”模型来编制的。在这种模型中,应用程序需要读取(或写入)指定数量的字节,然后以它为基础执行一些计算。程序清单8 - 1展示的代码片断便是一个典型的例子。程序清单8-1 简单的锁定模式示例这段代码的问题在于,假如没有数据处于“待决”状态,那么r e c v函数可能永远都无法返回。这是由于从语句可以看出:只有从系统的输入缓冲区中读回点什么东西,才允许返回!有些程序员可能会在r e c v中使用M S G _ P E E K标志,或者调用i o c t l s o c k e( t 设置F I O N R E A D选项),在系统的缓冲区中,事先“偷看”是否存在足够的字节数量。然而,在不实际读入数据的前提下,仅仅“偷看”数据(如实际读入数据,便会将其从系统缓冲区中将其删除),可不是一件光彩的事情。我们认为,这是一种非常不好的编程习惯,应尽全力避免。在“偷看”的时候,对系统造成的开销是极大的,因为仅仅为了检查有多少个字节可用,便发出一个或者更多的系统调用。以后,理所当然地,还需要牵涉到进行实际r e c v调用,将数据从系统缓冲区内删除的开销。那么,如何避免这一情况呢?在此,我们的目标是防止由于数据的缺乏(这可能是网络出了故障,也可能是客户机出了问题),造成应用程序完全陷于“凝固”状态,同时不必连续性地检视系统网络缓冲!为达此目的,一个办法是将应用程序划分为一个读线程,以及一个计算线程。两个线程都共享同一个数据缓冲区。对这个缓冲区的访问需要受到一定的限制,这是用一个同步对象来实现的,比如一个事件或者M u t e x(互斥体)。“读线程”的职责是从网络连续地读入数据,并将其置入共享缓冲区内。读线程将计算线程开始工作至少需要的数据量拿到手后,便会触发一个事件,通知计算线程:你老兄可以开始干活了!随后,计算线程从缓冲区取走(删除)一个数据块,然后进行要求的计算。第8章计Winsock I/O方法计计173下载在程序清单8 - 2中,我们分别提供了两个函数,采取的便是上述办法。在两个函数中,一个负责读取网络数据( R e a d T h r e a d),另一个则负责对数据执行计算( P r o c e s s T h r e a d)。程序清单8-2 多线程的锁定套接字示例174计计第二部分附Winsock API下载第8章计Winsock I/O方法计计175下载对锁定套接字来说,它的一个缺点在于:应用程序很难同时通过多个建好连接的套接字通信。使用前述的办法,我们可对应用程序进行修改,令其为连好的每个套接字都分配一个读线程,以及一个数据处理线程。尽管这仍然会增大一些开销,但的确是一种可行的方案。唯一的缺点便是扩展性极差,以后想同时处理大量套接字时,恐怕难以下手。8.1.2 非锁定模式除了锁定模式,我们还可考虑采用非锁定模式的套接字。尽管这种套接字在使用上存在着些许难度,但只要排除了这项困难,它在功能上还是非常强大的。除具备锁定套接字已有的各项优点之外,还进行了少许扩充,功能更强。程序清单8 - 3向大家展示了如何创建一个套接字,并将其置为非锁定模式。程序清单8-3 设置一个非锁定套接字将一个套接字置为非锁定模式之后, Winsock API调用会立即返回。大多数情况下,这些调用都会“失败”,并返回一个W S A E W O U L D B L O C K错误。什么意思呢?它意味着请求的操作在调用期间没有时间完成。举个例子来说,假如在系统的输入缓冲区中,尚不存在“待决”的数据,那么r e c v(接收数据)调用就会返回W S A E W O U L D B L O C K错误。通常,我们需要重复调用同一个函数,直至获得一个成功返回代码。在表8 - 2中,我们对常见Wi n s o c k调用返回的W S A E W O U L D B L O C K错误的含义进行了总结。由于非锁定调用会频繁返回W S A E W O U L D B L O C K错误,所以在任何时候,都应仔细检查所有返回代码,并作好“失败”的准备。许多程序员易犯的一个错误便是连续不停地调用一个函数,直到它返回成功的消息为止。例如,假定在一个紧凑的循环中不断地调用r e c v,以读入2 0 0个字节的数据,那么与使用前述的M S G _ P E E K标志来“轮询”一个锁定套接字相比,前一种做法根本没有任何优势可言。为此, Wi n s o c k的套接字I / O模型可帮助应用程序判断一个套接字何时可供读写。锁定和非锁定套接字模式都存在着优点和缺点。其中,从概念的角度说,锁定套接字更易使用。但在应付建立连接的多个套接字时,或在数据的收发量不均,时间不定时,却显得极难管理。而另一方面,假如需要编写更多的代码,以便在每个Wi n s o c k调用中,对收到一个176计计第二部分附Winsock API下载W S A E W O U L D B L O C K错误的可能性加以应付,那么非锁定套接字便显得有些难于操作。在这些情况下,可考虑使用“套接字I / O模型”,它有助于应用程序通过一种异步方式,同时对一个或多个套接字上进行的通信加以管理。表8-2 非锁定套接字上的W S A E W O U L D B L O C K错误函数名说明W S A A c c e p t和a c c e p t 应用程序没有收到连接请求。再次调用,便可检查连接情况c l o s e s o c k e t 大多数情况下,这个错误意味着已随S O _ L I N G E R选项一道,调用了s e t s o c k o p t,而且已设定了一个非零的超时值W S A C o n n e c t和c o n n e c t 应用程序已初始化。再次调用,便可检查是否完成W S A R e c v、r e c v、W S A R e c v F r o m和r e c v f r o m 没有收到数据。稍后再次检查W S A S e n d、s e n d、W S A S e n d To和s e n d t o 外出数据无缓冲区可用。稍后再试
 
Z

zuping

Unregistered / Unconfirmed
GUEST, unregistred user!
SOCKET通信时,阻塞模式和非阻塞到底有什么不同?阻塞,要等数据返回才会继续执行下句程序,有假死现象非阻塞,有点类似 SendMessage和PostMessage的区别,执行后,立即执行下1句程序 分别用语哪些场合?阻塞用于发送严谨的数据流、按照一定格式发送的网络数据的情形,我用过自己编写发送 符合网络协议的数据流,必须用1个线程单独发送,否则,程序卡死;非阻塞用于发送 允许丢失、要求不严格的数据;两种模式在编码时应该注意些什么?阻塞用于发送按照一定格式的数据流,按照格式要求发,外部主界面有中止发送、中止线程的命令就可以了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
958
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
顶部