1
ksc010 2021-11-11 14:45:32 +08:00
太长了,没细看
一般直接用 tcp 协议通讯的话,都设置自定义消息包格式 消息头+消息体 消息头长度固定,头里面包含消息体的长度,这样就知道读取多少位数据停止了 |
2
rrfeng 2021-11-11 14:49:01 +08:00
不要 ReadTo ,每次用 ReadAll 全读出来,然后另外拆分处理?
|
3
bfdh 2021-11-11 15:17:23 +08:00
如果对端支持 udp 的话,换 udp 吧,感觉 udp 这种协议设计。使用 tcp 确实存在你说的问题。
如果非得用 tcp ,又不愿意改协议,那就你的接收端加超时,一定时间内没有新的数据达到,就认为是一条消息结束。 |
5
ysc3839 2021-11-11 16:35:41 +08:00
这个设计是有问题,看起来 Received 的作用只是控制是否补发,那客户端发完后就应该直接 shutdown ( https://man7.org/linux/man-pages/man2/shutdown.2.html ),这样服务端就能知道数据已经发完了,这个方案甚至不需要修改数据包格式。
|
6
ysc3839 2021-11-11 16:38:44 +08:00
@rrfeng 这里的问题是客户端发完数据后不会 shutdown ,ReadAll 要等客户端 shutdown 后才会返回。
|
7
momocraft 2021-11-11 16:42:02 +08:00
想办法避免无限阻塞的 API
|
8
ipwx 2021-11-11 16:42:42 +08:00
解决方案:
1 、每个客户端给一个 shutdownRequested 变量。 2 、自己开缓冲区处理 ReadTo('#') 的逻辑,用异步 read 。 3 、read 读不到就返回,那么进入 epoll 等待队列。 4 、如果 shutdownRequested ,就唤醒这个 fd 去处理。。 总结: 需要一个完整的 event loop 。但是有了就很容易做 |
9
FreeWong OP @rrfeng 实际编程语言没有 ReadAll , 如果你的意思是 总是从缓冲区去读,每次读一批,然后接收缓冲区就有了位置,对端才可以继续发送数据过来。但是你如何判断你接收完了? 像这样
声明 512 长度的字节数组 for{ 得到的数据= 读到 512 长度的字节数组() 如果( 得到的数据以用 # 号结尾则是一个完成的数据 ) } 但这是有问题的,如果你正好读的最后一个字符是两条数据中间的 # ,你会认为所有的数据都接收完了 ,实际上还有余下的一个完整的没有被接收下来, 如果你认为读到一个 # 不是所有数据都接收完了,那何时能判断哪个 # 号才表示接收完成? |
11
FreeWong OP @bfdh 超时是个办法,但不是一个好办法,我可以定义 5 秒钟都收完,如果收不完,也就结束 了,但这种方式真的不好
|
12
FreeWong OP |
14
ysc3839 2021-11-11 16:58:08 +08:00
客户端改不了的情况下有一个可能可行的方案,就是服务端一收到数据就立即发送 Received ,然后 read all 直到断开连接,这个方案可行的前提是客户端会把所有数据发完再断开连接。假设客户端是发送数据、接收数据、断开连接顺序执行的话,这个方案是可行的。
|
16
ipwx 2021-11-11 17:01:57 +08:00
@FreeWong 不这就是很常见的解决方案。
只不过在比如 python 语言里面你可以用协程 asyncio ,在 node.js 里面可以用回调,把上面的逻辑实现是个很简单的事情。在 C++ 里面你就不得不用多线程或者 event loop 了。 |
17
ysc3839 2021-11-11 17:03:35 +08:00
@FreeWong 所以你到底能不能改客户端?能改的话那个方法是可行的。本质是用 # 代替 shutdown 来表示“数据已发完”。
|
21
Sricecake 2021-11-15 13:14:25 +08:00
问题点在于 TCP 是流式的,你却把它当 HTTP 用。
正常应该是每条数据应该有个 ID 你收到一个# 就回一条 Received(ID) 你只负责一直循环 ReadTo 处理完一条就回一条 Received 客户端判断所有消息都 Received 了再断开连接就行。 |
22
FreeWong OP @Sricecake 客户端的现在的错误逻辑,就是我只要回一条接收到的消息, 它就断开了。。如果客户端自己还有很多数据要发,它照样断 。。。这本来就是在一个错误的逻辑上修补。
客户端是硬件厂商做的,我无法修改 |
23
Sricecake 2021-11-19 19:22:40 +08:00
按 #19 的说法 方法可行的话让供应商下个版本修改,按正确逻辑改了就可以了吧。
|
24
FreeWong OP 我的问题是,我的方法是否可行,有没有逻辑上说不通的地方。。
|