以下内容由
[五四陈科学院]提供
- 实际开发中,网络程序最可能遇到的就是数据没收到、收到错误数据这样诡异的问题.
- 很多时候,都是由于对socket read的细节理解的不一致,导致了程序前后的矛盾。
- 下面详细阐述整个read的过程。
一、从c的角度
ssize_t read(int fd,void *buf,size_t nbyte)
二、从协议角度
- TCP协议是面向流的
- read和write调用的返回值往往小于参数指定的字节数。
- 对于read调用,如果接收缓冲区中有20字节,请求读100个字节,就会返回20。
- 对于write调用,如果请求写100个字节,而发送缓冲区中只有20个字节的空闲位置,那么write会阻塞,直到把100个字节全部交给发送缓冲区才返回,但如果socket文件描述符有O_NONBLOCK标志,则write不阻塞,直接返回20。
三、从java的角度
SocketChannel sc = (SocketChannel) sk.channel();
int i = sc.read(buff)
- SocketChannel.read 有数据时返回数据长度。
- 如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误(继承自C)。
- 而linux的函数是针对文件fd出现的定义,如果是网络时,EOF的界限十分模糊。
四、从kernel的角度
static int unix_stream_recvmsg(struct kiocb iocb, struct socket sock,
struct msghdr *msg, size_t size,
int flags)
五、从java nio的框架角度
- 结合java nio的selector机制,要对read为0的情况进行统计处理。
- 同一源过多的read为0,意味着网络不好,或者恶意攻击。
想快点找到作者也可以到Twitter上留言:
@54chen或者你懒得带梯子上墙,请到新浪微博:
@54chen