C/S框架 st_asio_wrapper 开发教程(2019.10.17更新)(四)

如果你偶然浏览到这里,请先看 C/S框架 st_asio_wrapper 开发教程(一)
源代码及例程下载地址:
git:https://github.com/youngwolf-project/st_asio_wrapper/
QQ交流群:198941541

九:陷阱

        大家都知道多线程死锁,进程间死锁,今天我要说的是,两台网络通信中的电脑,也会死锁,不可思议吧?那么st_asip_wrapper会死锁吗?请往下看。
        先举个网络编程中死锁的典型例子,假如AB两个程序做网络通信(谁是服务端谁是客户端无所谓),都采用单线程阻塞模式,假设在某个时刻,A因发送缓存满而被阻塞在send,此时B(AB在不同电脑上,所以理论上,他们完全不相干涉,换句话说,无论A处于什么业务状态, B都有可能处于任意一个业务状态)完全有可能也因为发送缓存满而被阻塞在send,由于A被阻塞在send,说明B的接收缓存满了(不满的话,数据总是会从A到达B的,数据的接收是由网络驱动自动做的,不管我们是否接收数据,它总是会在可能的情况下尽量接收数据到本地缓存),由于B被阻塞在send,说明A的接收缓存也满了(原理同前面所说)。两个套接字的四个缓存都满!此时,死锁就发生了,要想让A从send返回,B必须从自己的接收缓存里面读取一些数据,以便让A发送一些数据到B。可是不幸的是,B被阻塞在send,它没机会执行recv来读取一些数据。反之已然。
        那么大家为什么很少遇到上面的情况呢,因为四个缓存都满,需要一些特定的条件,就是两边的发送一定要非常快,不一定要一直快,当死锁一但发生,马上把速度降下来也没用了(其实根本就没速度了,因为卡住了),死锁无法自解。如果你对你的产品做压力测试,相信可能会遇得上的。
        那么st_asio_wrapper是否会死锁呢?如果你因为等待发送缓存可用而阻塞在on_msg_handle,死锁是有可能发生的,没错,多线程异步IO居然要死锁,其原因是消息处理(on_msg_handle)被阻塞,一但数据接收被停止,那么情况和单线程阻塞模式是一样的。
        注意,要不是因为等待发送缓存可用而阻塞在on_msg_handle(两端都这样),都是没有问题的,大家也不要太害怕,比如你阻塞在on_msg_handle里面处理自己的业务,或者阻塞在其它地方,比如你自己的线程都是没有问题的。换句话说,只要不阻塞在service线程里面,或者即便阻塞在service线程,但解除阻塞的条件与本socket的发送缓存可用性无关,就不会造成死锁,只会有限的阻塞,死锁是无限的阻塞。
        更方便简洁但有些暴力的方法是,以can_overflow为true调用send_msg(相当于发送缓存永远可用),这个就需要开发者保证缓存不会达到不可控的直线上升状态,也就是总要有让缓存减少的机制,或者业务本身在达到某个高度之后,就会下降,这些情况下,都可以让can_overflow为true。
        那么到底要怎样做拥塞控制呢,具体请参看教程第五篇

十:线程安全性

        默认情况下service_pump开启8个IO线程,只要线程数量多于1个,那么所有的回调方法(以on开关的虚函数),都是并发的(除非是明显有顺序关系的,且在同一个socket对象上的时候),具体说来(以on_msg_handle和on_msg_send为例):对于同一个socket,on_msg_handle和on_msg_send是并发的,on_msg_handle和on_msg_handle(下一个)、on_msg_send和on_msg_send(下一个)是顺序的;对于不同的socket,所有回调都是并发的。
        关于定时器回调的并发性,不同timer之间当然是并发,同一个timer对象的同一个timer(以id区分timer)回调是顺序,不同的timer的回调是并发的。注意:多线程对同一个timer对象调用set_timer设置同一个timer(id相同)是不安全的,设计即是这样(否则每一个timer对象里面的每一个timer都需要一个互斥对象)。
        其它的方法,除了明显不应该设计为多线程的(比如初始化,开始结束服务等),都是线程安全的,比如send_msg等。

十一:关于文件传输工具的使用

        这是我写的两个基于st_asio_wrapper的demo,file_server和file_client,支持简单的聊天和文件分块传输,在局域网里面,最好别分块,因为瓶颈在磁盘IO,如果从互联网上传输,则分块肯定可以提高速度,就像迅雷一样。
        使用方法很简单,把要传输的文件放到file_server能访问到的地方,开启file_server。file_client的运行方式是:file_client link_num,其中每一条连接代表一个文件块,如果要分5块同时下载,则link_num设为5,当file_client所有连接都成功连到服务器时,输入命令:get file_name1 file_name2 ...,开始以次传输每一个文件。输入其它任何内容则当成聊天信息直接发送。如果传送的文件不在当前路径,比如 get ../123/a.txt,则要求客户端也必须存在../123这个目录,这个如果你觉得是问题的话,可以修改demo。

st_asio_wrapper使用FAQ
C/S框架 st_asio_wrapper 开发教程(五)
 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
st_asio_wrapper是一组类,功能是对boost.asio的包装(调试环境:boost-1.51.0),目的是简化boost.asio开发; 其特点是效率高、跨平台、完全异步,当然这是从boost.asio继承而来; 自动重连,数据透明传输,自动解决分包粘包问题(你可以像udp一样使用它); 注:只支持tcp协议; 教程:http://blog.csdn.net/yang79tao/article/details/7724514 1.1版更新内容: 增加了自定义数据模式的支持,可用于st_asio_wrapper server与其它客户端的通信、或者st_asio_wrapper client与其它服务端的通信;当然,两端都是st_asio_wrapper的话,就用透明传输即可(1.0版已经支持了)。 1.2版更新内容: 修复BUG:当stop_service之后,再start_service时,client_base内部某些成员变量可能没有得到复位; 服务端增加修改监听地址功能,当然仍然要在start_service之前调用set_server_addr函数。 1.3版更新内容: 增加自定义消息格式的发送,这个本来是在1.1版本实现的,结果我漏掉了,只实现了自定义消息格式的接收。 1.4版更新内容: 将打包与解包器从client_base分离出来,以简化这个日益复杂的基类; 可以在运行时修改打包解包器。 1.5版更新内容: 增加ipv6支持,默认是ipv4,服务端和客户端都通过设置一个ipv6的地址来开启这个功能; 增加了一些服务端helper函数,小改了一下客户端set_server_addr函数签名(调换了两个参数的位置以保持和服务端一样)。 1.6版更新内容: 增加了接收消息缓存(改动较大,on_msg的语义有所变化,请看开发教程第三篇)。 1.7版更新内容: 修复vc2010下编译错误; 修复默认解包器BUG(同时修改解包器接口); 修复log输出BUG; 更好的包装了服务端类库,现在服务端可以像客户端一样简单的使用了(完全不用继承或者重写虚函数,申请一个对象即可); 结构大调整,类名大调整,请参看开发教程第一篇。 1.8版更新内容: 增加健壮性和稳定性; 退出服务更新优雅。 1.9版更新内容: 提高代码通用性; 可以指定服务端同时投递多少个async_accept; 修复BUG,此BUG可能造成数据发送不完全。 2.0版更新内容: 服务端增加对象池功能; 优化美化代码; 更规范化接口签名。 2.1版更新内容: 修复BUG,此BUG会造成st_client在stop_service之后,仍然可能尝试重新连接服务器; 在消息发送的时候,增加了一个参数can_overflow,用于确定是否在缓存满的时候返回失败,这在某些不能阻塞等待直到缓存可用的场合非常有用,比如on_msg; 当消息接收缓存满的时候,st_socket现在可以保证消息不丢失,之前的行为是调用on_recv_buffer_oveflow之后,丢弃消息; 更规范化接口签名; 更多更新请看st_asio_wrapper_socket.h,所有更新都会罗列在这个头文件的开头处,另外st_asio_wrapper_server.h的开头部分注释也很重要,有工作原理相关的说明。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值