linux的read函數从鍵盤讀取,Linux网络中的read函数

这是一篇查漏补缺的文章,探究一下linux网络编程中read函数的几种返回值,以及分别在什么情况下发生的,当然也会顺带提及 TCP 的一点点知识(毕竟谈到网络是离不开TCP的)。

为了验证,写了一个 client 和 server 来测试相关的东西。

TCP的三次握手和三次挥手

是的,你没看错,是三次挥手,而不是四次。一般情况下,TCP在建立连接是需要三次握手,在断开连接时需要四次挥手,但是有时只需要三次挥手就够了,下图是我用tcpdump的抓包情况:aaadbadf004f3537f5401546fa9e55d1.pngtcp连接过程

上图可以分为三个部分:建立连接,三次握手,红色部分;

数据传输,蓝色部分;

关闭连接,三次挥手,紫色部分。

对应TCP的传输过程如下:39c7c6f891f4aa29b6f1ec895b2aa36a.pngtcp传输过程

出现三次挥手的原因是因为,被动关闭连接的一端(本图中的 server 端)缓冲区内没有需要发送的数据,所以将ACK 和 FIN 合并发送给了 Client 端。如果 server 端收到 FIN 时缓冲区内还有未发送的数据,那么 server 端会先回 ACK,等到数据发送完成,再发送 FIN,这样就是通常我们看到的四次挥手了。

阻塞模式下对 read/write 的测试

测试1

流程如下:24cdfe680aca0f2f5f25478c92c5b883.png测试1

结果:

当缓冲区还有未读取的数据时,调用 close 函数关闭 socket,会触发 TCP 发送 RST,此时对方等到数据接收,调用 read 函数,会得到 -1 的返回值,errno 被设置为104 (Connection reset by peer),如果在收到 RST 之后仍然继续调用 write 函数,会触发系统的 SIGPIPE 信号,导致程序退出(如果未处理该信号的话)。049def7f1b20523e0631f96dee6eedb9.pngsigpipe信号

测试2

流程如下:e07d1be847a49b1cc0be4750e3e15c72.png测试2

结果:

当对方已经关闭连接时(即对方发送了 FIN),此时再调用 write 写数据,会触发对方发送一个 RST,如果忽略 SIGPIPE 信号,继续 write 数据,得到的返回值是 -1,errno被设置为32(Broken pipe)。

测试3

流程如下:db8ebdb12756dabc38e00ea73099cede.png测试3

结果:

调用 setsockopt 给read设置一个超时时间(setsockopt(sockfd, SOL_SOCKET,SO_RCVTIMEO, &ti, sizeof(ti)); ),超时之后,read函数返回-1,errno被设置为11(Resource temporarily unavailable)。

非阻塞模式下对read的测试

使用 fcntl 设置socket为非阻塞模式,调用 read 的结果是会立刻返回 -1,然后errno被设置为了11。

结论

read 函数返回值:大于0:成功读取的数据长度(Byte);

等于0:该 socket 已经关闭;

等于-1:异常发生,包括但不限于以下几种:

超时,errno=11;

连接异常关闭(RST),errno=104;

主动关闭socket后再去 read,errno=9;

非阻塞模式下的没有数据时,errno=11。

write 函数返回值:大于0:成功写入的数据长度(Byte);

等于0:写入长度为0;

小于0:异常发生,包括但不限于以下几种:

主动关闭再写数据,errno=9;

连接异常关闭(RST)之后再写数据,errno=32。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值