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

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

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

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

1 a 2 bc 3 c3s

因为按照协议来,你的数据就是完全对应的,不可能读到 c 的时候,或者读到倒数第二个 3 的时候,代码逻辑会误判为长度
hjc4869
2017-08-02 10:50:05 +08:00
用 socket::available()?
sc3263
2017-08-02 13:50:21 +08:00
@fyyz proxy ?各种各样的数据?
只转发不做处理的话,把 async_read_some 读出来的数据再发出去就行了。
如果需要过滤内容的话,又或者说,你需要读取完整的一个包然后再整个发送出去。你肯定得知道对应的协议,协议里面肯定约定了长度字段。那你就按照那个协议做处理就行了。
如果和$$一样,读取数据,加密一下转发给服务器。那就自己定义一个协议,上面也有人说了,最简单的,开头 4 个字节表示这个包的长度,然后是包的剩余内容,读完长度之后读取剩余的部分。你打包一下,服务器解包一下。
mathgl
2017-08-02 21:36:31 +08:00
@fyyz 你的 proxy 处理的什么格式的数据?有没有通信协议。如果都没有统一标准那是很麻烦的事。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/379660

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX