1
laoyur 2022-09-03 17:15:20 +08:00
链接不对
|
2
cnbatch 2022-09-03 17:24:09 +08:00
目录列表有个醒目的“粘包处理”
很好,看来又开启了 V2EX 流量密码 |
3
cnbatch 2022-09-03 17:39:10 +08:00 6
看了下 FAQ ,又发现“TCP 粘包处理”。这是 V2EX 老生常谈的话题,略。
再粗略搜了下源码,发现它并不使用各系统的异步 API (IOCP / kqueue / epoll / io_uring 全都未使用),而是使用 O_NONBLOCK + std::thread 来达到“异步”的效果。 重新看了下介绍,“专注于客户端”。原来如此。 |
4
justanetizen OP @cnbatch 客户端的重心不在并发,而在 gui 的 fluent ,多线程是必需的
|
5
cnbatch 2022-09-03 22:19:21 +08:00
行吧,我来拆拆潜台词:
客户端的重心不在并发——所以觉得没必要用系统自己的异步 API ,也不想用已有的各大异步网络库 而在 gui 的 fluent——所以只想关注 GUI 的交互,不想手动处理报文细节,也不想处理 TCP 流数据 多线程是必需的——由于没用到系统异步 API ,只能选择多线程去处理 |
6
justanetizen OP @cnbatch 我是一个 emacs 用户,对 C/C++原生桌面软件比较熟悉的也就 emacs 了,虽然经验不算资深,但断断续续接触 emacs 也快十年了(扯远了),之所以说到多线程,刚好 emacs 很大一部分的卡顿原因或者问题源头就是因为其单线程架构,emacs 社区(包括中文社区)最近也在讨论其单线程架构和解决方向,至于你说的其他什么异步 API 、粘包之类的,我相信不是什么难点,而之所以推荐那个库,我主要也是看到了其多线程、异步 IO 的特点,至于如何实现,我没有细看哈,我不🦌Cpp 的。
|
7
cnbatch 2022-09-04 18:13:30 +08:00
仅仅是因为“多线程”和“异步 IO”啊……
对于 yasio 的 FAQ 提到的其它网络库库 (asio libevent libev libuv) 来说,“异步 IO”本身同样就是标配,这没什么好说的。这几个库一样都支持多线程,其中部分默认多线程的库可以配置成单线程异步 IO 模式,默认单线程的库也提供多线程环境的支持。 可以说,如果仅仅只是“多线程”和“异步 IO”,那么另外那几个库同样达标,而且做得更好。 yasio 的“亮点”在于“粘包处理”(从 TCP 流数据中自动拆出所需数据),要不然它也不会醒目地单独放在目录列出来;以及内置 KCP 库(游戏行业比较喜欢使用 KCP 传数据),在“预处理器”那里有提到;还有跟部分游戏引擎的交互支持,在 Github 说明那里有提到。 这些显然不是你的关注点。 |
8
justanetizen OP @cnbatch 爱用不用吧,那库也不是我写的,与其在这里和我硬杠,不如直接去人家 repo 提 pr
|
9
cnbatch 2022-09-04 20:01:32 +08:00
@justanetizen 并不是在杠,而是觉得你的关注点(是各个库都有的共性,只不过 yasio 列了出来而已)完全偏离了人家原作者的关注点(游戏行业的痛点),人家原作者并不是仅仅为了“多线程”而多线程、为了“异步”而异步。
我列了这么一堆字是告诉你原作者的关注点是什么。 |
10
justanetizen OP @cnbatch talk is cheap, 上代码吧,只要能证明你说的是对的就行
|
11
cnbatch 2022-09-04 20:42:48 +08:00
真奇怪,代码本身就是开源的,介绍也是现成的,完全可以自己看的呀……
而且我前面那些,哪句话说错了? 也行,那就列一次出来,包括代码和它们各自的说明: yasio: 首页自己的介绍:“专注于客户端和基于各种游戏引擎的游戏客户端网络服务” 内置 KCP: https://github.com/yasio/thirdparty/tree/0264931f4af65f9532863d37c2cc206604d16918 游戏引擎支持: https://github.com/yasio/yasio_unity https://github.com/yasio/yasio_unreal TCP 流数据拆包(“粘包”): https://yasio.github.io/yasio/3.39.4/unpacking/ 以上都是其它异步网络库不具备的。 C++asio: https://think-async.com/Asio/asio-1.24.0/doc/asio/using.html 预定义 ASIO_DISABLE_THREADS 可关闭多线程支持。 即默认使用多线程。 至于“异步”,名字就说明一切了。 libev: https://github.com/enki/libev/blob/master/ev.c#L768 https://stackoverflow.com/questions/14621261/using-libev-with-multiple-threads http://blog.leanote.com/post/simon88/2f29107bd8dc (第三方博客) https://developer.aliyun.com/article/801557 可以看出,能够自行选择多线程还是单线程模式 https://metacpan.org/dist/EV/view/libev/ev.pod 说明文档,搜索“async”可以看见异步的说明 libevent: https://libevent.org/ 人家首页直接就说了:Libevent can also be used for multi-threaded applications, either by isolating each event_base so that only a single thread accesses it, or by locked access to a single shared event_base. 关键部分—— [也] 能支持多线程 意思就是默认单线程,但同样可以多线程 更进一步的说明: https://quant67.com/post/ioevent/multithread-libevent.html (第三方网站) 如何使用 libevent 实现异步网络编程: https://gist.github.com/ajhwb/3685796 libuv: https://github.com/libuv/libuv 项目说明直接就写了出来: Asynchronous TCP and UDP sockets Asynchronous DNS resolution Asynchronous file and file system operations Threading and synchronization primitives 清清楚楚。 |
12
justanetizen OP @cnbatch 周末在忙其他的,没空看你的回复,我搞不清楚你到底在反驳什么,或者在质疑什么,好像一方面你觉得那个库 ok ,但是,一方面又要告诉我别人关注的是什么,我之所以分享那个库,真就是觉得你们搞游戏那一行有点过于个人主义了,对待好东西就像你对待那个库的 attitude 一样,有点自我矛盾。
|
13
cnbatch 2022-09-05 16:15:28 +08:00 1
事先声明,我不是游戏行业。
首先,推荐某样东西,肯定需要跟大家说“为什么”、“好在哪”吧?尤其是标题写着“不错”两个字,那么是哪方面的“不错”?然而重新看看这个帖子,除了贴了个链接,什么都没讲。这给人一种很莫名其妙,甚至有一种“广告”的感觉。 第二,再看看链接,显然连接到错误页面了( 1 楼就有提到),会给人一种“敷衍”的感觉。不清楚这是 V2EX 的自动替换还是怎样。 既然没说好在哪,那就进去看看它的各种特点,并随意点评。 1, “TCP 粘包”这种说法早就被 V2EX 的各种讨论贴吐槽过很多次,总地来说大家的观点是,讲出“TCP 粘包”这种字眼等于主动引战,属于不专业的表现。 2 ,使用 O_NONBLOCK + std::thread 算不上“不错”,这纯粹为了省事,“能用就行”。再看一眼介绍,“专注于客户端”,难怪。由于是在客户端跑,一般只会建立个位数的连接,所以大多数情况下都无所谓,察觉不出。 3, 为了搞清楚为什么作者会“偷懒”,自然要进去看看它的介绍,包括 Github 页面。看完后发现,原来作者的着重点并不是单纯的“异步”,而是为了给游戏同行提供一个集成化的、一站式的解决方案,免得每次使用其他异步库时都需要重新手写代码处理诸如“TCP 流数据拆包”、叠一层 KCP 库、游戏引擎交互之类的麻烦事。 看得出,作者的精力都放在游戏引擎交互、游戏脚本语言的交互、游戏行业常用网络功能的整合。 结论就是,这个库是专门为游戏行业量身打造的。它所带的特色功能,其他人几乎用不上。 接下来,你从 emacs 解释了为什么会关注这个库,原来是因为“多线程”和“异步 IO”的支持。 既然如此,那我就只好作出提醒,支持多线程和异步 IO 支持是各大 C++网络库的基础性操作,并不是特色、特点,也不是专属优点。 除了前面提到的另外 4 个库,实际上其他的 C++网络库,或者带网络支持的 C++库,也是这样。 比如阿里巴巴的 PhotonLibOS: https://github.com/alibaba/PhotonLibOS/blob/main/net/kernel_socket.cpp 搜索下就可以看到,用了 pthread (多线程),epoll (异步 IO ) |
14
justanetizen OP @cnbatch 你说的对,以后不乱推荐了 :)
|
15
deal11 2022-09-06 00:02:25 +08:00 via Android
异步只是结果或效果,epoll/kqueue/io_uring/iocp/poll/select+非阻塞 socket 可以实现,线程+阻塞 socket 也可以实现,协程也可以实现
|
16
deal11 2022-09-06 00:27:31 +08:00 via Android
游戏里的处理耗时事务,例如大量资源加载,分帧加载也是实现异步的一种思路,可有效避免界面卡顿。
不管是 iocp/epoll 等,还是 select/poll 都是实现多路 io 复用模型的方式,只是前者适用于实现高并发的服务器,后者多数情况下更适合适用于客户端,但无论如何,离开 nonblocking io(socket),高并发是空谈,异步 io 也是空谈。 |
17
deal11 2022-09-06 00:33:04 +08:00 via Android
当然,线程+阻塞 socket 也能实现异步,但线程资源更昂贵,这也是个各操作系统提供类似 epoll/kqueue/iocp/io_uring/select/poll+非阻塞 socket 多路 io 复用模型的原因。
|
18
deal11 2022-09-06 00:43:48 +08:00 via Android
O_NONBLOCK + std::thread 算不上“不错”,这句话有误导。任何程序都离不开线程,libuv,asio 等离开 thread 也啥都干不了,任何进程至少有一个线程不是。std::thread 只是一种封装接口。看 yasio 文档,可以通过 YOPT_S_NO_THREAD 禁用内部创建线程,这样,所有网络消息和事件都在 io_service.run 调用者线程执行,至于这个线程是进程主线程还是其他线程,就取决于用户业务了。
tips: asio 的多路 io 复用模型 backend 也有 select 的实现,只是默认都用各平台高并发模型 epoll/kequeue/iocp/io_uring ,但可通过编译选项禁用他们,然后 fallback 到 select |
20
deal11 2022-09-06 16:12:41 +08:00
我猜题主之所以关注到 yasio ,是因为该库 github 标题提到: "any client applications"
|
21
deal11 2022-09-06 16:20:08 +08:00
@deal11 看 yasio 的源码,正是使用的 select + nonblocking socket 多路 io 复用模型,select api 几乎可以跨所有操作系统平台。
|
22
deal11 2022-09-13 11:53:13 +08:00 via Android
所谓系统级的异步 API, 目前已知:iocp 和 io_uring 吧
|