关于 readn、writen 函数--read返回值分析


转自:http://blog.csdn.net/atefrice/article/details/47861891




一、zebra 中的 源码,readn、writen




二、调用readn、writen的原因


1、socket上的read write操作不同与一般的文件IO操作;

2、socket上的用read write读写的字节数可能比要求的少,但这并不是错误;

3、原因是socket的缓冲区可能已经到达了极限,或者被信号中断;

4、所以,此时所需要的就是再次调用read write以写入或输出剩余的字符,于是有了 readn、writen。


三、readn的代码分析

原文链接:http://m.blog.csdn.net/blog/u011542994/44684173


1、nleft表示还剩下的字节数;nread表示已经读取的字节数
2、接着是一个字符型指针变量:ptr,指向读取的目标缓冲区(ptr = vptr)
3、我们要读取的时n字节的数据,于是就先将赋值:nleft = n;(当前初始时,还剩了n个字节等待读取呢)
4、接着进入循环while,只要还剩下了字节也就是 nleft>0,就进入循环:
5、开始read, if( nread < 0 ),意味着read函数这里出现了问题(也许是出错了,也许是中断影响了它)
6、接着进行问题的处理:errno 是记录系统的最后一次错误代码(在errno.h中定义);

7、而EINTR则是返回状态,不同函数意义不同;

8、read中表示:由于信号中断,没读到任何数据;

9、if(errno == EINTR)意思就是说如果read是因为中断导致返回负数(nread < 0),那么此时将nread置0;

      即:nread = 0,表示什么也没有读取到,那么此时还要继续重新再次调用read函数,再次读取数据(依然在
      while循环内进行);

10、如果不是因为中断导致read异常那么就返回-1,跳出循环;

11、如果nread = 0,说明此时数据数据已经读取完了或者对端关闭连接,也是要跳出循环。
12、最后函数返回读取的字节数(极端情况就是nleft = 0了,也就是没有剩余的数据,显然返回的就是n;那么只要             nleft>0,while会一直进行下去)

13、writen 类似。


四、read返回值分析

注意: 源代码级详细精彩的分析在这里  原文链接:http://blog.chinaunix.net/uid-23629988-id-3035613.html


以下只是概括:

1、当receive queue 为空时,   socket错误或者  对端 close、shutdown都会导致read  返回0;

2、若receive queue 小于请求 read 字节数时,才会进入 判断是否有 信号pending,

                                 如果有信号,呢么返回值受 copied 值确定, 

                                                       若copied > 0, 则返回值即为copied(必然小于请求字节),

                                                       若copied ==0,则返回值为-1,   并且errno 被设定为EINTR;

      若receive queue 大于 请求 read 字节数时,则不会 进行 信号pending 的检查。

3、综上,对端关闭后,是否可以读取对端在关闭之前发送的数据??

      答:只要receive queue中有数据,就不会去检查是否sk_shutdown的标志(对端close或shutdown产生该标志);

             只要receive queue中有足够的数据,就不会去检查  是否有信号pending

              因此,即使对端关闭socket,本端仍可以读取对端在关闭之前发送的数据!!!!!



五、从tcp报文角度,分析一端挂死

注意: 原文链接:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201212075929354/




如上图所示,

1、Server进程被终止,此时Server会正常发送FIN包给Client

                                       操作系统在回收socket描述符时,就像close一样,会发送FIN包给Client。

2、如果此时Client继续向Server写数据,那么会触发一个RST包。

3、总结: 在Linux下,无论是read位于FIN包和RST包之间,还是read位于FIN包和RST包之后,read都将返回0。                                       所以当read返回0时,可以确认对方已经关闭了连接,所以接下来应该关闭socket描述符

                 当TCP的发送队列中还有数据没有发送完成时,调用close操作,不会发送FIN包,而是发送RST包。



一、zebra 中的 源码,readn、writen




二、调用readn、writen的原因


1、socket上的read write操作不同与一般的文件IO操作;

2、socket上的用read write读写的字节数可能比要求的少,但这并不是错误;

3、原因是socket的缓冲区可能已经到达了极限,或者被信号中断;

4、所以,此时所需要的就是再次调用read write以写入或输出剩余的字符,于是有了 readn、writen。


三、readn的代码分析

原文链接:http://m.blog.csdn.net/blog/u011542994/44684173


1、nleft表示还剩下的字节数;nread表示已经读取的字节数
2、接着是一个字符型指针变量:ptr,指向读取的目标缓冲区(ptr = vptr)
3、我们要读取的时n字节的数据,于是就先将赋值:nleft = n;(当前初始时,还剩了n个字节等待读取呢)
4、接着进入循环while,只要还剩下了字节也就是 nleft>0,就进入循环:
5、开始read, if( nread < 0 ),意味着read函数这里出现了问题(也许是出错了,也许是中断影响了它)
6、接着进行问题的处理:errno 是记录系统的最后一次错误代码(在errno.h中定义);

7、而EINTR则是返回状态,不同函数意义不同;

8、read中表示:由于信号中断,没读到任何数据;

9、if(errno == EINTR)意思就是说如果read是因为中断导致返回负数(nread < 0),那么此时将nread置0;

      即:nread = 0,表示什么也没有读取到,那么此时还要继续重新再次调用read函数,再次读取数据(依然在
      while循环内进行);

10、如果不是因为中断导致read异常那么就返回-1,跳出循环;

11、如果nread = 0,说明此时数据数据已经读取完了或者对端关闭连接,也是要跳出循环。
12、最后函数返回读取的字节数(极端情况就是nleft = 0了,也就是没有剩余的数据,显然返回的就是n;那么只要             nleft>0,while会一直进行下去)

13、writen 类似。


四、read返回值分析

注意: 源代码级详细精彩的分析在这里  原文链接:http://blog.chinaunix.net/uid-23629988-id-3035613.html


以下只是概括:

1、当receive queue 为空时,   socket错误或者  对端 close、shutdown都会导致read  返回0;

2、若receive queue 小于请求 read 字节数时,才会进入 判断是否有 信号pending,

                                 如果有信号,呢么返回值受 copied 值确定, 

                                                       若copied > 0, 则返回值即为copied(必然小于请求字节),

                                                       若copied ==0,则返回值为-1,   并且errno 被设定为EINTR;

      若receive queue 大于 请求 read 字节数时,则不会 进行 信号pending 的检查。

3、综上,对端关闭后,是否可以读取对端在关闭之前发送的数据??

      答:只要receive queue中有数据,就不会去检查是否sk_shutdown的标志(对端close或shutdown产生该标志);

             只要receive queue中有足够的数据,就不会去检查  是否有信号pending

              因此,即使对端关闭socket,本端仍可以读取对端在关闭之前发送的数据!!!!!



五、从tcp报文角度,分析一端挂死

注意: 原文链接:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201212075929354/




如上图所示,

1、Server进程被终止,此时Server会正常发送FIN包给Client

                                       操作系统在回收socket描述符时,就像close一样,会发送FIN包给Client。

2、如果此时Client继续向Server写数据,那么会触发一个RST包。

3、总结: 在Linux下,无论是read位于FIN包和RST包之间,还是read位于FIN包和RST包之后,read都将返回0。                                       所以当read返回0时,可以确认对方已经关闭了连接,所以接下来应该关闭socket描述符

                 当TCP的发送队列中还有数据没有发送完成时,调用close操作,不会发送FIN包,而是发送RST包。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值