一个关于 TCP 粘包的问题.

2014-04-14 00:41:47 +08:00
 paulw54jrn
需要用c实现一个简单的C/S程序.
Client端因为需要在收到SIGIO信号之后在Handler里面接受字节流,Server端使用Select()轮询可用的FileDescriptor. 每次发送的字节数固定不变(recv的大小预先知道).
两边公用的接收代码如下:
https://gist.github.com/10591146

现在的问题是程序经常跑飞,在客户端经常会发现接收的字节数为-1;
Bytes received -> -1 , need more bytes 4170

在服务器端有时可以成功,有时会失败,收到字节数为0:
Bytes received -> 0 , need more bytes 4170;

问题是是,如果客户端收到了SIGIO信号后,不是能够说明TCP管道中有数据可以被读,那为什么初选recv == -1 的情况? 同理,服务器端使用Select(),不是同样说明管道中有数据,为何读取的时候字节数为0?

Google过关于TCP Message Fragment的问题,建议是用循环把包拼起来,直到大小正确为止.但是目前用这个办法效果不太好. 是我哪里写的不对?
2757 次点击
所在节点    问与答
4 条回复
alexapollo
2014-04-14 00:49:13 +08:00
man recv
这是一个基础问题。
xdeng
2014-04-14 01:11:03 +08:00
-1断开?
paulw54jrn
2014-04-14 08:23:35 +08:00
@alexapollo
man page 我看过,我也明白这是一个基础问题. 也许正是太基础了,网上的描述都比较简单. 按照网上的建议,试了用几种不同的方式来把数据拼接在一起,但是都会有问题. 我觉得是我对Signal和Select的理解不够,所以想看看大家的意见.

除了吐槽之外,还请'请尽量让自己的回复能够对别人有帮助'.
vietor
2014-04-14 09:39:18 +08:00
SIGPIPE应该disable掉,同时对于粘包使用一定的拼接缓冲区是无法避免的。此外,使用SIGIO来作为事件通知也太古老了,难道是mac环境?

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

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

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

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

© 2021 V2EX