epoll 在 EPOLLIN 的时候怎么确定数据已经读完

2014-09-28 10:27:52 +08:00
 wudikua
我写了一个ECHO SERVER,用的是LT触发,在EPOLLIN的时候,通过4K一个BUFFER读数据,当读到的数据大于0,并且小于4K的时候就认为已经读完了,然后触发EPOLLOUT开始写数据。现在问题是当发送的数据长度是4K*N倍的时候,按照上面的逻辑会数据读完,但是没有触发EPOLLOUT,而EPOLL又因为句柄的接收队列上已经没有数据了而不会触发EPOLLIN了,这个是不是很无解??我想了一下,解决我这个问题有几种方法,第一种,如果有检测FD是不是还有数据的方法,但是不读,那我就可以在读到的字节数等于4K的时候检测一下是不是还有数据,如果没有数据了就EPOLLOUT。第二种,先读一个固定大小的头部,然后头部里写了数据的长度,这样根据已经读到的长度就知道是不是需要触发EPOLLOUT。第三种,客户端写数据故意不写BUFFER_SIZE * N大小,通过一些0x0来填充。求个正解的方法。
5443 次点击
所在节点    程序员
11 条回复
heiher
2014-09-28 11:36:23 +08:00
为什么读完才out?
heiher
2014-09-28 11:38:03 +08:00
qsun
2014-09-28 11:45:21 +08:00
socket设置成非堵塞,每次EPOLLIN事件发生都不停的读,直到read返回-1,并且 errono 是 EAGAIN 或者 EWOULDBLOCK,这样才代表socket中没有数据了。具体的可以看 READ(2)

另外,你说的一个数据块4k,socket并不会buffer这些数据,所以每次都去可能是4k可能不是4k,1~4k都是可能的。所以你需要人肉管理对应的接收到的数据buffer。
wudikua
2014-09-28 12:54:08 +08:00
@heiher 这个是一边READ一边WIRTE,如果要求把数据READ完才知道要WRITE什么,你这样就不行了。
wudikua
2014-09-28 12:58:36 +08:00
@qsun 你说的这个和我说的没关系啊,如何在非阻塞的SOCKET上READ我已经处理了,我的问题是我读了一个BUFFER,返回了已经读的字节数是BUFFER的长度,怎么知道返回读到的字节数是因为已经读完所以返回BUFFER_SIZE,还是因为还有数据所以返回BUFFER_SIZE
cloveryume
2014-09-28 13:03:28 +08:00
TCP?TCP没有读完的概念,除非说关闭。
TCP是一个流,肯定还要有更上一层的应用层协议,报头+报体,报头长度固定,内部有个字段表示报体的长度。可以甄别一个完整的报文。
heiher
2014-09-28 13:07:32 +08:00
@wudikua 你的这种情况是传输的数据是以一定的长度为一个 message 的,那你就增加 header 吧,然后在处理那边如果需要处理一个完整的 message 的话,只能使用一个 context 保存着 buffer list 或使用一个足够大的 buffer 存储 message。
wudikua
2014-09-28 13:47:33 +08:00
@cloveryume 看来应该是这样~想再问个问题,报体如果不是一次WRITE,而是按照BUFFER分段WRITE,在服务器接收的时候是按照WRITE的顺序接收的么,还是可能会乱序,还得像TCP一样加个序号。
cloveryume
2014-09-28 16:56:11 +08:00
@wudikua 按照顺序,前提是中间没有穿插其他线程的写入。也需要检查write调用的返回值。
比较常见的一种做法是一个连接对应一个outbuf,写数据的时候写到这个outbuf里。
同时检测EPOLLOUT事件,可写时,就从outbuf里拿,往底层socket write。
songco
2014-09-29 13:44:02 +08:00
最好用第二种方式, tcp是流, 应用层协议要自己知道什么时候一个消息读完整了. 比如特殊的结束符, 比如先发四字节的长度.

如果消息是同步的, 应该有办法不加长度信息也能完成你说的, 不过比较麻烦, 如果是异步的就必须加了.
luoqeng
2014-09-29 13:56:28 +08:00
一般的网络库读了数据之后要更新下写的回调函数

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

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

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

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

© 2021 V2EX