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 开发教程(五)
 

为了在Windows安装ADB工具,你可以按照以下步骤进行操作: 1. 首先,下载ADB工具包并解压缩到你自定义的安装目录。你可以选择将其解压缩到任何你喜欢的位置。 2. 打开运行窗口,可以通过按下Win+R键来快速打开。在运行窗口中输入"sysdm.cpl"并按下回车键。 3. 在系统属性窗口中,选择"高级"选项卡,然后点击"环境变量"按钮。 4. 在环境变量窗口中,选择"系统变量"部分,并找到名为"Path"的变量。点击"编辑"按钮。 5. 在编辑环境变量窗口中,点击"新建"按钮,并将ADB工具的安装路径添加到新建的路径中。确保路径正确无误后,点击"确定"按钮。 6. 返回到桌面,打开命令提示符窗口。你可以通过按下Win+R键,然后输入"cmd"并按下回车键来快速打开命令提示符窗口。 7. 在命令提示符窗口中,输入"adb version"命令来验证ADB工具是否成功安装。如果显示版本信息,则表示安装成功。 这样,你就成功在Windows安装ADB工具。你可以使用ADB工具来执行各种操作,如枚举设备、进入/退出ADB终端、文件传输、运行命令、查看系统日志等。具体的操作方法可以参考ADB工具的官方文档或其他相关教程。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [windows环境安装adb驱动](https://blog.csdn.net/zx54633089/article/details/128533343)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Windows安装使用ADB简单易懂教程](https://blog.csdn.net/m0_37777700/article/details/129836351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值