异步/同步、阻塞/非阻塞的理解

本文深入探讨了同步与异步、阻塞与非阻塞在网络通信中的概念与应用,通过日常生活类比帮助理解。详细解释了同步与异步的区别,以及它们在服务器上的表现,同时对比了阻塞与非阻塞调用的特性,提供了直观的理解路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[同步和异步]

通俗的讲:
同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。 
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事
异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕

概念从现实中来:
同步:打电话,你拨通电话后必须等在那里,直到对方有人接了,你们才能通信或者说你才能继续打下一个电话。
异步:发短信,你可以发短信,只要你发出去,你就可以继续发给下一个人,而不需要等到第一个人回你,你才可以继续。

同步服务器
异步服务器
所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。按照这个定义,其实绝大多数函数都是同步调用(例如sin, isdigit等)。
但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。最常见的例子就是 SendMessage。
该函数发送一个消息给某个窗口,在对方处理完消息之前,这个函数不返回。当对方处理完毕以后,该函数才把消息处理函数所返回的 LRESULT值返回给调用者。

异步
异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
以CAsycSocket类为例(注意,CSocket从CAsyncSocket派生,但是起功能已经由异步转化为同步),当一个客户端通过调用 Connect函数发出一个连接请求后,
调用者线程立刻可以朝下运行。当连接真正建立起来以后,socket底层会发送一个消息通知该对象。这里提到执行部件和调用者通过三种途径返回结果:
状态、通知和回调。可以使用哪一种依赖于执行部件的实现,除非执行部件提供多种选择,否则不受调用者控制。
如果执行部件用状态来通知,那么调用者就需要每隔一定时间检查一次,效率就很低
(有些初学多线程编程的人,总喜欢用一个循环去检查某个变量的值,这其实是一种很严重的错误)。
如果是使用通知的方式,效率则很高,因为执行部件几乎不需要做额外的操作。至于回调函数,其实和通知没太多区别。

[阻塞和非阻塞]

阻塞
阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。
有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。
对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。
例如,我们在CSocket中调用Receive函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。
而此时,当前线程还会继续处理各种各样的消息。如果主窗口和调用函数在同一个线程中,除非你在特殊的界面操作函数中调用,其实主界面还是应该可以刷新。
socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候,如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。

非阻塞
非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

通俗地说,你拿着饭碗在排队等饭是阻塞的,你不能跑出去干其他事情;你拿着一张取饭的号码等饭是非阻塞的,你可以出去抽根烟在回来。

比如在epoll模型wait之后,将新连接设置成一个非阻塞的连接(见epoll模型)
 setnonblocking(client); // 将新连接置于非阻塞模式
这样客户端在得到结果之前,立刻返回,而不是出于等待中。

在网络通信与服务器编程过程中,我们必须首先了解这两组蛋疼的概念!但是,当你模糊时候,请想到
“打电话和发短信”,“拿饭碗等和拿号码等饭”,那么你就清楚了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值