ascs 简明开发教程(二十):消息发送完成通知与消息派发(接收)的顺序性

31 篇文章 0 订阅
31 篇文章 1 订阅

QQ交流群:198941541

消息发送完成通知即on_msg_send和on_all_msg_send,消息派发指的是on_msg和on_msg_handle(包括批量异步派发和单条异步派发),先抛出结论,不要对这两类回调的先后顺序做任何假设,即便是on_msg_send与on_msg也一样(它们都属于收发线程,还记得在上一篇教程里面说的每个socket里面都有两个线程吗?)。

显然地,如果消息发送与接收没任何关联,那消息发送完成通知与消息派发显然是没有先后顺序的,我们说一个很特殊的案例,a发送一个消息给b,b收到消息再原样返回(应答模式),a接收这个消息,然后ab都停止数据收发,这个案例在a上看起来最像是有先后顺序的,如果它的顺序都无法保证,那么我们可以说——消息发送完成通知与消息派发(接收)是没有顺序性的

先看看99.99%情况下的回调顺序(on_msg_send在前,on_msg_handle或者on_msg在后):

再看看0.01%情况下的,on_msg_handle或者on_msg在后的情况:

所以我们只能把on_msg_send和on_all_msg_send看成单纯的一个事件通知,不能假设它与消息派发有什么先后顺序。那我非要整出个先后关系怎么办呢(业务需要)?那还是有办法的,ascs库的设计原则我在群里面说过,就是能极简也能深度定制,具体到这个问题,我们先说说它的root cause,因为每个socket,后台始终有一个async_read,我们只需要停止它,然后在on_msg_send里面再开启它,就完美解决问题。为此我们必须定义宏ASCS_PASSIVE_RECV,它的意思是由使用者触发异步读取(通过recv_msg),但在连接建立起来之后的的第一个async_read,ascs还是会自动调用,为此还得定义宏ASCS_SYNC_RECV,这样第一个async_read也不会被调用了。注意这可能会带来另一个问题,就是你的service_pump启动之后,如果你没来得及发送数据,那么servicp_pump会认为它没有事可干,就会自动结束自己(asio::io_context的设计),为此我们通过再定义宏ASCS_AVOID_AUTO_STOP_SERVICE来解决这个问题。

总结一下,对于on_msg_send, on_all_msg_send, on_msg, on_msg_handle,只有自己与自己是有先后顺序的(即前一个消息的on_msg_send一定先与后一个消息的on_msg_send,其它回调也一样),它们之间的顺序不应做任何假设,哪怕它们来自同一个线程(收发线程或者消息派发线程),只有on_msg_send和on_all_msg_send有点例外,我们知道,当发送缓存变空时,会连续收到on_msg_send和on_all_msg_send(其它时候不会有on_all_msg_send),此时on_msg_send一定在on_all_msg_send之前。

上一篇 ascs 简明开发教程(19)下一篇 ascs 简明开发教程(21)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值