boost::asio 中, async_read_some() 如何判断包是否读完了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fyyz
V2EX    C

boost::asio 中, async_read_some() 如何判断包是否读完了

  •  
  •   fyyz 2017-08-01 22:56:43 +08:00 4716 次点击
    这是一个创建于 2997 天前的主题,其中的信息可能已经有所发展或是发生改变。
    17 条回复    2017-08-02 21:36:31 +08:00
    owt5008137
        1
    owt5008137  
       2017-08-01 23:09:35 +08:00 via Android
    很久没碰过 boost::asio 了。不过一般情况下,如果是 tcp,你得自己加包头。判定是否读完了一整个包,你要自己做黏包。
    我不记得他是来一个包回调一次还是一定要收到你指定的长度才回调。如果是后者,你在调用这个函数前就要保证传入的长度小于等于总长度
    woshixiaohao1982
        2
    woshixiaohao1982  
       2017-08-01 23:16:18 +08:00
    去网上找一个 lineparse 就好了,一般可以采取 /r/n 等作为结束符
    alqaz
        3
    alqaz  
       2017-08-01 23:36:03 +08:00
    不是发送每个数据包之前发送一个固定长度的表示数据包长度的数据吗?
    fyyz
        4
    fyyz  
    OP
       2017-08-02 02:01:43 +08:00 via Android
    @owt5008137 包头是类似整个包 size 的东西吗?
    fyyz
        5
    fyyz  
    OP
       2017-08-02 02:02:40 +08:00 via Android
    @woshixiaohao1982 这个方法我在不少地方看到过,但是我这里不行,因为我要传二进制数据,可能数据内部正好出现这个字符
    fyyz
        6
    fyyz  
    OP
       2017-08-02 02:03:07 +08:00 via Android
    @alqaz 你是指 tcp 的包头中的吗?
    AngelCriss
        7
    AngelCriss  
       2017-08-02 08:25:53 +08:00 via Android
    @fyyz 同学,你知道为什么 HTTP 头里面有一个长度吗?
    fyyz
        8
    fyyz  
    OP
       2017-08-02 08:28:04 +08:00 via Android
    @AngelCriss 我当然知道,可是我现在写的是 proxy,可能会收到各种各样的包,不可能为每种包都写一个获取长度的方法啊。
    newkedison
        9
    newkedison  
       2017-08-02 08:53:51 +08:00
    这个问题我也很纠结,现在用 asio 写串口和 TCP,由于传输的是二进制,所以无法用包头包尾或者长度的办法,只能通过接收时间间隔判断。

    目前的做法是 async_read_some 传入的 buffer 小一点(比如 10 ),然后在 handler 里面再次 async_read_some,同时启动一个定时器,定时一小段时间(比如 10ms ),时间到了就调用 cancel() ,从而表示一包结束。

    不过这样做的话,通讯速率肯定就上不去了
    owt5008137
        10
    owt5008137  
       2017-08-02 08:55:36 +08:00 via Android
    @fyyz 包头包含长度。proxy 的话可以提供某种机制让被代理方定这个包头。要么或者你就用流的转发
    slowman
        11
    slowman  
       2017-08-02 09:01:58 +08:00
    转义字符
    shibingsw
        12
    shibingsw  
       2017-08-02 09:31:14 +08:00
    tcp 是字节流,没有包的概念,你可以自己在每个消息头部加上消息的长度,比如用 4 个自己做长度,每次接收消息的时候先接收 4 个字节,算出长度,然后根据这个长度调用 async_read_some,每次得到的长度累加起来,直到算出的长度。
    alqaz
        13
    alqaz  
       2017-08-02 10:18:12 +08:00 via Android
    @fyyz 当然不是,就是你的发送端要发送多少数据之前面加一个表示长度的字段。
    araraloren
        14
    araraloren  
       2017-08-02 10:29:53 +08:00
    @fyyz 就算你只传输一个长度值都能实现一个非常简单的协议,不会有什么内部出现某某字符的问题

    1 a 2 bc 3 c3s

    因为按照协议来,你的数据就是完全对应的,不可能读到 c 的时候,或者读到倒数第二个 3 的时候,代码逻辑会误判为长度
    hjc4869
        15
    hjc4869  
       2017-08-02 10:50:05 +08:00
    用 socket::available()?
    sc3263
        16
    sc3263  
       2017-08-02 13:50:21 +08:00
    @fyyz proxy ?各种各样的数据?
    只转发不做处理的话,把 async_read_some 读出来的数据再发出去就行了。
    如果需要过滤内容的话,又或者说,你需要读取完整的一个包然后再整个发送出去。你肯定得知道对应的协议,协议里面肯定约定了长度字段。那你就按照那个协议做处理就行了。
    如果和$$一样,读取数据,加密一下转发给服务器。那就自己定义一个协议,上面也有人说了,最简单的,开头 4 个字节表示这个包的长度,然后是包的剩余内容,读完长度之后读取剩余的部分。你打包一下,服务器解包一下。
    mathgl
        17
    mathgl  
       2017-08-02 21:36:31 +08:00
    @fyyz 你的 proxy 处理的什么格式的数据?有没有通信协议。如果都没有统一标准那是很麻烦的事。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5316 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 05:48 PVG 13:48 LAX 22:48 JFK 01:48
    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