暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

动图图解!代码执行send成功后,数据就发出去了吗?

IT技术精选文摘 2021-10-27
1482

若有收获,请记得分享和转发哦

代码执行send成功后,数据就发出去了吗?

回答这个问题之前,需要了解什么是Socket 缓冲区


Socket 缓冲区

什么是 socket 缓冲区

编程的时候,如果要跟某个IP建立连接,我们需要调用操作系统提供的 socket API

socket 在操作系统层面,可以理解为一个文件

我们可以对这个文件进行一些方法操作

listen
方法,可以让程序作为服务器监听其他客户端的连接。

connect
,可以作为客户端连接服务器。

send
write
可以发送数据,recv
read
可以接收数据。

在建立好连接之后,这个 socket 文件就像是远端机器的 "代理人" 一样。比如,如果我们想给远端服务发点什么东西,那就只需要对这个文件执行写操作就行了。

socket_api

一个socket有两个缓冲区


怎么观察 socket 缓冲区

如果想要查看 socket 缓冲区,可以在linux环境下执行 netstat -nt
 命令。

答案是不确定!执行 send 之后,数据只是拷贝到了socket 缓冲区。至 什么时候会发数据,发多少数据,全听操作系统安排。

tcp_sendmsg 逻辑

在用户进程中,程序通过操作 socket 会从用户态进入内核态,而 send方法会将数据一路传到传输层。在识别到是 TCP协议后,会调用 tcp_sendmsg 方法。

send阻塞
  • 如果此时 socket 是非阻塞的,程序就会立刻返回一个 EAGAIN
     错误信息,意思是  Try again
     , 现在缓冲区满了,你也别等了,待会再试一次。

send非阻塞

我们可以简单看下源码是怎么实现的。还是回到刚才的 tcp_sendmsg
 发送方法中。

如果接收缓冲区为空,执行 recv 会怎么样?

如果socket缓冲区还有数据,执行close了,会怎么样?

首先我们要知道,一般正常情况下,发送缓冲区和接收缓冲区 都应该是空的。

如果发送、接收缓冲区长时间非空,说明有数据堆积,这往往是由于一些网络问题或用户应用层问题,导致数据没有正常处理。

那么正常情况下,如果 socket
 缓冲区为空,执行 close
。就会触发四次挥手。

TCP四次挥手

这个也是面试老八股文内容了,这里我们只需要关注第一次挥手,发的是 FIN
 就够了


socket
 缓冲区是个先进先出的队列,这种情况是指内核会等待TCP层安静把发送缓冲区数据都发完,最后再执行 四次挥手的第一次挥手(FIN包)。

有一点需要注意的是,只有在接收缓冲区为空的前提下,我们才有可能走到 tcp_send_fin()
 。而只有在进入了这个方法之后,我们才有可能考虑发送缓冲区是否为空的场景。

UDP部分

UDP也有缓冲区吗

说完TCP了,我们聊聊UDP。这对好基友,同时都是传输层里的重要协议。既然前面提到TCP有发送、接收缓冲区,那UDP有吗?

以前我以为。

"每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。"

后来我发现我错了。

而我们大部分情况下,都不会用  MSG_MORE
,也就是来一个数据包就直接发一个数据包。从这个行为上来说,虽然UDP用上了发送缓冲区,但实际上并没有起到"缓冲"的作用。

文章转载自IT技术精选文摘,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论