推荐一个不错的 Cplusplus 网络库 - V2EX
请不要在回答技术问题时复制粘贴 AI 生成的内容
justanetizen

推荐一个不错的 Cplusplus 网络库

  •  
  •   justanetizen Sep 3, 2022 2936 views
    This topic created in 1348 days ago, the information mentioned may be changed or developed.
    22 replies    2022-09-13 11:53:13 +08:00
    laoyur
        1
    laoyur  
       Sep 3, 2022
    链接不对
    cnbatch
        2
    cnbatch  
       Sep 3, 2022
    目录列表有个醒目的“粘包处理”

    很好,看来又开启了 V2EX 流量密码
    cnbatch
        3
    cnbatch  
       Sep 3, 2022   6
    看了下 FAQ ,又发现“TCP 粘包处理”。这是 V2EX 老生常谈的话题,略。

    再粗略搜了下源码,发现它并不使用各系统的异步 API (IOCP / kqueue / epoll / io_uring 全都未使用),而是使用 O_NONBLOCK + std::thread 来达到“异步”的效果。

    重新看了下介绍,“专注于客户端”。原来如此。
    justanetizen
        4
    justanetizen  
    OP
       Sep 3, 2022
    cnbatch 客户端的重心不在并发,而在 gui 的 fluent ,多线程是必需的
    cnbatch
        5
    cnbatch  
       Sep 3, 2022
    行吧,我来拆拆潜台词:

    客户端的重心不在并发所以觉得没必要用系统自己的异步 API ,也不想用已有的各大异步网络库
    而在 gui 的 fluent所以只想关注 GUI 的交互,不想手动处理报文细节,也不想处理 TCP 流数据
    多线程是必需的由于没用到系统异步 API ,只能选择多线程去处理
    justanetizen
        6
    justanetizen  
    OP
       Sep 3, 2022
    @cnbatch 我是一个 emacs 用户,对 C/C++原生桌面软件比较熟悉的也就 emacs 了,虽然经验不算资深,但断断续续接触 emacs 也快十年了(扯远了),之所以说到多线程,刚好 emacs 很大一部分的卡顿原因或者问题源头就是因为其单线程架构,emacs 社区(包括中文社区)最近也在讨论其单线程架构和解决方向,至于你说的其他什么异步 API 、粘包之类的,我相信不是什么难点,而之所以推荐那个库,我主要也是看到了其多线程、异步 IO 的特点,至于如何实现,我没有细看哈,我不Cpp 的。
    cnbatch
        7
    cnbatch  
       Sep 4, 2022
    仅仅是因为“多线程”和“异步 IO”啊……

    对于 yasio 的 FAQ 提到的其它网络库库 (asio libevent libev libuv) 来说,“异步 IO”本身同样就是标配,这没什么好说的。这几个库一样都支持多线程,其中部分默认多线程的库可以配置成单线程异步 IO 模式,默认单线程的库也提供多线程环境的支持。

    可以说,如果仅仅只是“多线程”和“异步 IO”,那么另外那几个库同样达标,而且做得更好。

    yasio 的“亮点”在于“粘包处理”(从 TCP 流数据中自动拆出所需数据),要不然它也不会醒目地单独放在目录列出来;以及内置 KCP 库(游戏行业比较喜欢使用 KCP 传数据),在“预处理器”那里有提到;还有跟部分游戏引擎的交互支持,在 Github 说明那里有提到。
    这些显然不是你的关注点。
    justanetizen
        8
    justanetizen  
    OP
       Sep 4, 2022
    @cnbatch 爱用不用吧,那库也不是我写的,与其在这里和我硬杠,不如直接去人家 repo 提 pr
    cnbatch
        9
    cnbatch  
       Sep 4, 2022
    @justanetizen 并不是在杠,而是觉得你的关注点(是各个库都有的共性,只不过 yasio 列了出来而已)完全偏离了人家原作者的关注点(游戏行业的痛点),人家原作者并不是仅仅为了“多线程”而多线程、为了“异步”而异步。

    我列了这么一堆字是告诉你原作者的关注点是什么。
    justanetizen
        10
    justanetizen  
    OP
       Sep 4, 2022
    @cnbatch talk is cheap, 上代码吧,只要能证明你说的是对的就行
    cnbatch
        11
    cnbatch  
       Sep 4, 2022
    真奇怪,代码本身就是开源的,介绍也是现成的,完全可以自己看的呀……
    而且我前面那些,哪句话说错了?

    也行,那就列一次出来,包括代码和它们各自的说明:

    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
    清清楚楚。
    justanetizen
        12
    justanetizen  
    OP
       Sep 5, 2022
    @cnbatch 周末在忙其他的,没空看你的回复,我搞不清楚你到底在反驳什么,或者在质疑什么,好像一方面你觉得那个库 ok ,但是,一方面又要告诉我别人关注的是什么,我之所以分享那个库,真就是觉得你们搞游戏那一行有点过于个人主义了,对待好东西就像你对待那个库的 attitude 一样,有点自我矛盾。
    cnbatch
        13
    cnbatch  
       Sep 5, 2022   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 )
    justanetizen
        14
    justanetizen  
    OP
       Sep 5, 2022
    @cnbatch 你说的对,以后不乱推荐了 :)
    deal11
        15
    deal11  
       Sep 6, 2022 via Android
    异步只是结果或效果,epoll/kqueue/io_uring/iocp/poll/select+非阻塞 socket 可以实现,线程+阻塞 socket 也可以实现,协程也可以实现
    deal11
        16
    deal11  
       Sep 6, 2022 via Android
    游戏里的处理耗时事务,例如大量资源加载,分帧加载也是实现异步的一种思路,可有效避免界面卡顿。
    不管是 iocp/epoll 等,还是 select/poll 都是实现多路 io 复用模型的方式,只是前者适用于实现高并发的服务器,后者多数情况下更适合适用于客户端,但无论如何,离开 nonblocking io(socket),高并发是空谈,异步 io 也是空谈。
    deal11
        17
    deal11  
       Sep 6, 2022 via Android
    当然,线程+阻塞 socket 也能实现异步,但线程资源更昂贵,这也是个各操作系统提供类似 epoll/kqueue/iocp/io_uring/select/poll+非阻塞 socket 多路 io 复用模型的原因。
    deal11
        18
    deal11  
       Sep 6, 2022 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
    deal11
        19
    deal11  
       Sep 6, 2022 via Android
    @deal11 YOPT_S_NO_NEW_THREAD
    deal11
        20
    deal11  
       Sep 6, 2022
    我猜题主之所以关注到 yasio ,是因为该库 github 标题提到: "any client applications"
    deal11
        21
    deal11  
       Sep 6, 2022
    @deal11 看 yasio 的源码,正是使用的 select + nonblocking socket 多路 io 复用模型,select api 几乎可以跨所有操作系统平台。
    deal11
        22
    deal11  
       Sep 13, 2022 via Android
    所谓系统级的异步 API, 目前已知:iocp 和 io_uring 吧
    About     Help     Advertise     Blog     API     FAQ     Solana     3977 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 61ms UTC 05:06 PVG 13:06 LAX 22:06 JFK 01:06
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86