IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    有关socket read

    五四陈科学院发表于 2014-11-18 20:37:49
    love 0

    以下内容由[五四陈科学院]提供

    • 实际开发中,网络程序最可能遇到的就是数据没收到、收到错误数据这样诡异的问题.
    • 很多时候,都是由于对socket read的细节理解的不一致,导致了程序前后的矛盾。
    • 下面详细阐述整个read的过程。

    一、从c的角度

    ssize_t read(int fd,void *buf,size_t nbyte)

    • read函数是负责从fd中读取内容.
    • 当读成功时, read返回实际所读的字节数
    • 如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误。

    • 可以同时检查errno:

    • 如果错误为EINTR(值为4)说明读是由中断引起的
    • 如果是ECONNREST表示网络连接出了问题

    二、从协议角度

    • 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)
    
    • http://blog.chinaunix.net/uid-23629988-id-3035613.html
    • 这篇文章的主人详细分析了整个过程。
    • 当网卡上没有数据时,返回为0。
    • 另外在对端单独close write或者自己单独close read时,也返回0。
    • 当数据取完了,且出现意外的系统调用,比如网卡故障,返回-1。

    五、从java nio的框架角度

    • 结合java nio的selector机制,要对read为0的情况进行统计处理。
    • 同一源过多的read为0,意味着网络不好,或者恶意攻击。

    想快点找到作者也可以到Twitter上留言: @54chen
    或者你懒得带梯子上墙,请到新浪微博:@54chen


沪ICP备19023445号-2号
友情链接