[转载请注明:出自cnblogs,作者:byeyear,Email:east3@163.com]

[2012.10.08: 完善文章内容]

本文主要讨论几个在网络编程中经常被讨论但也经常被误解的概念:

阻塞(Blocking),非阻塞(Non-Blocking),同步(Sync),异步(Async),重叠(Overlapped)。

首先要明确的是,只有那些会导致发生“数据传输”的函数(accept,connect,send,recv等)才存在这些概念;像bind、listen这些不会引发“数据传输”的函数,是不存在“阻塞非阻塞”或“同步异步”这样的问题的。

其次一个比较重要的问题是,Non-Blocking和Async不是一回事。在一些论坛文章和关于网络编程的书中,将这两者等同,这是不正确的。

1. Blocking和Non-Blocking

Blocking:只有在函数所请求的操作完成后,函数才会返回。例如,accept会等到连接队列非空才返回;recv会等到数据缓冲区中有数据后才返回。因此,blocking的意思是,操作若不能完成函数就不返回。

Non-Blocking:如果操作无法立即完成,send/recv这样的函数将以失败返回,函数所请求的操作不会得到执行。同时WSAGetLastError函数将返回WSAEWOULDBLOCK。例如,如果缓冲区中没有数据,recv会立即返回。在Non-Blocing模式下,程序可以通过一个循环不停调用recv,直到有数据可用。

2. Sync、Async和Overlapped

Sync:App层的函数调用和OS底层的动作是顺序的。例如,App调用recv -> OS执行recv -> 执行完成 -> 函数返回。

Async:App层的函数调用和OS底层的动作是非顺序的。例如,App以填充好的Overlapped结构调用WSARecv,即使无数据可读,函数也会立即返回,但OS底层仍然会继续执接收数据的工作,并在有数据可用时以event、callback或completion port的形式通知App。而Overlapped和Async实际上是一个概念。之所以叫“Overlapped”,是指多次函数调用可以重叠进行。例如,你可以在有数据可读前多次调用WSARecv。如果一个Async IO不能立即完成,函数将以失败返回,同时你WSAGetLastError将返回WSA_IO_PENDING。但是,底层的操作将继续执行。你的程序将在稍后得到通知。

3. Blocking/Non-Blocking通过ioctlsocket设定,设定完成后,后续的send/recv将遵循最经一次的ioctlsocket设置。

4. overlapped和两方面有关:一是通过WSASocket创建socket时是否设定了overlapped标记(socket默认设置overlapped),二是WSASend/WSARecv调用是否提供overlapped结构。

4.1 如果WSASocket没有设定overlapped,那么这个socket将是sync的且不可改变,WSASend/WSARecv的行为和send/recv类似;

4.2 如果WSASocket设定了overlapped,那么有三种情况:

4.2.1 使用send/recv。这两个函数不支持overlapped,所以函数行为是sync的;

4.2.2 使用WSASend/WSARecv,但不提供overlapped结构。函数行为同样是sync的;

4.2.3 使用WSASend/WSARecv,并且提供overlapped结构。函数行为时Async的。App将在数据可用时得到通知。

从上文可以看出,即使为socket设定了overlapped attribute,仍然可以对该socket使用非overlapped函数调用。换句话说,ASync/overlapped仅是socket所具备的一个“功能”,你可以用,也可以不用。这和Non-Blocking是不同的,在那里,一旦设定了Non-Blocking,函数调用必定是Non-Blocking的。

综上,我们可以得到socket I/O操作的几种方法:

a) Blocking,Sync:这个是最简单的。连接建立后,App调用recv或send收发数据。

b) Non-Blocking,Sync:使用ioctlsocket将指定socket设置为Non-Blocking。在ioctlsocket之后,若数据不可用,recv或send将返回WSAEWOULDBLOCK。

c) Blocking,Async:若无数据可用,send或recv函数将Blocking。WSARecv和WSASend将立即返回,并在有数据可用时通知App。

d) Non-Blocing,Async:在无数据可用的情况下,send/recv将返回WSAEWOULDBLOCK,WSARecv/WSASend将返回SOCKET_ERROR。区别在于,send/recv除了立即返回以外不会有别的效果,而WSARecv和WSASend虽然也是立即返回,但它们所请求的操作将由OS继续执行,直到有数据可用后通知App。

宝书《Windows网络编程》中所述的几种Model,实际上就是Blocking/Non-Blocking和Sync/Async的不同组合。

a) 阻塞模式:Blocking + Sync

b) 非阻塞模式:Non-Blocking + Sync。App通过不停调用send/recv获取数据。

c) select模式:Blocking + Non-Sync。和a)的区别在于,阻塞在select上而不是send/recv上。select保证后续的send/recv操作不会阻塞,看起来好像是Non-Blocking一样——但实质上仍然是Blocking模式。

d) WSAEventSelect/WSAAsyncSelect:Non-Blocking + Sync。这两个函数会自动将socket设置为Non-Blocking(MSDN如是说)。和b)的区别在于由OS负责在数据可用时发出Message或SetEvent,不需要App自己Polling。

e) Overlapped:Blocking + ASync。在这种情况下,一般不会使用send/recv函数而是使用WSASend或WSARecv,所以Blocking不会成为问题。如果你不小心在这种model下使用了send/recv,那么这两个函数仍然会在无数据可用的情况下blocking住。

参考文档:http://support.microsoft.com/kb/181611/en-us?fr=1

Blocking/Non-Blocking VS Sync/Async VS Overlapped相关推荐

  1. spi sync async

    spi 的同步和异步传输 spi_async spi_sync 先看 spi_sync  return __spi_sync(spi, message, 0);   DECLARE_COMPLETIO ...

  2. java sync和async区别_GCD中串行、并行与async、sync的区别

    * author:conowen@大钟 * E-mail:conowen@hotmail.com 队列由一个或多个任务组成,当这些任务要开始执行时,系统会分别把他们分配到某个线程上去执行. 串行队列. ...

  3. 【从零开始学习 SystemVerilog】3.5、SystemVerilog 控制流——阻塞(Blocking)与非阻塞(Non-Blocking)

    文章目录 阻塞(Blocking) 非阻塞(Non-blocking) 阻塞(Blocking) Blocking赋值语句使用=赋值,并在程序块中一个接一个地执行.但是,这不会阻止在并行块中运行的语句 ...

  4. blocking与non_blocking

    blocking(b=a;) 阻塞赋值方式 gvim blocking 设计 module blocking(clk,a,c);input clk;input a;output c;reg c;reg ...

  5. Win32多线程 -- 异步IO(overlapped IO)

    一. 异步(overlapped) IO之被激发的File Handle 1.1 Win32 IO操作函数 Win32 之中有三个基本的函数用来执行 I/O      CreateFile()    ...

  6. C# 5.0功能之Async一瞥

    原文: http://www.cnblogs.com/xiaomi7732/archive/2011/06/27/AsyncDemo.html 距离微软发布 Async CTP 已经有个把月了吧,周围 ...

  7. oracle12C--DG FAR SYNC 部署(前提为搭建好12C的DG)

    <<往期12CDG搭建>> 一,理解同步异步模式 01, 使用LGWR 进程的SYNC 方式 1)Primary Database 产生的Redo 日志要同时写到日志文件和网络 ...

  8. 一文读懂Rust的async

    一文读懂Rust的async 不同的编程语言表现异步编程的方式可能不一样,Rust跟JavaScript的async/await类似:使用的关键字啊,编程模型啊都差不多啦! 也有些不一样的地方,毕竟R ...

  9. node.js async循环数组的方法

    Collections 集合处理 async.forEachOf  |  eachOf(object, iterator, callback) 实现功能:遍历object对象执行iterator,报错 ...

最新文章

  1. RPC框架——简单高效hessian的使用方式
  2. css有些效果不显示,css导入成功但没有效果怎么办
  3. linux删掉文件怎么恢复,linux系统误删除文件怎么恢复
  4. LeetCode 461 Hamming Distance(汉明距离)
  5. 光大银行刘淼:基于华为云GaussDB(DWS) 数据仓库创新实践
  6. javax包 rpc_javax.xml.rpc和javax.wsdl分别属于哪个jar包?
  7. 《Cisco IOS XR技术精要》一2.7 高可用架
  8. python中的shallow copy 和 deep copy
  9. 互联网公司的规律.txt
  10. LitePal 数据库使用方法(最新2.0LitePal数据库适用)
  11. java 僵尸进程_有关僵尸进程和孤儿进程的解释
  12. 服装设计与工程_百度百科
  13. sqluldr2支持mysql吗_sqluldr2工具使用方法
  14. GEE开发之Landsat8_NDVI的数据分析
  15. 人工智能python营_AI人工智能训练营
  16. 微信小程序开发-轮播图的实现
  17. c语言银行信用卡卡管理系统,自编自导多人多卡信用卡管理系统
  18. 前端总结·基础篇·CSS
  19. 德累斯顿工业大学计算机学院,德累斯顿工业大学
  20. Debian10.9离线安装gcc(附离线包地址)

热门文章

  1. 1.4激活函数-带隐层的神经网络tf实战
  2. HDU4417 Super Mario 主席树
  3. BZOJ3675 [APIO2014]序列分割
  4. MySQL 类型转换
  5. bzoj3626:[LNOI2014]LCA
  6. NOIP练习赛题目5
  7. 剑指offer重构二叉树 给出二叉树的前序和后序重构二叉树
  8. C#操作注册表增删改查及关机能保存问题
  9. C# 客户端HTTP通信
  10. 计算机专业颈椎有问题,出现这4个表现,你的颈椎病已经很严重了!上班族尤需警惕_39健康网...