网络编程离不开 Socket,Socket 就是发送和接收网络数据,Socket 有发送缓冲也有接收缓冲,这些缓冲区有什么作用?是一个什么机理呢?

这篇文章就是想跟大家分享一下 Socket 缓冲区的方方面面。

什么是 Socket 缓冲区

首先我们看看为什么 Socket 要有缓冲区,它起什么作用。 熟悉 Socket 的读者都知道,Socket 的发送和接收,就是调用 send 和 recv 函数。

实际操作中,我们将要发送的数据 buffer,送给 send 函数,然后 send 就会返回成功或者失败,那么,send 什么时候返回成功呢?是发送到对端函数才返回吗?答案是否定的。(注意:Socket 有同步和异步,本文主要讨论 Socket 缓冲区,不深究异步,都假定是同步)

实际上呢,Socket 有一个缓冲区,send 的数据 buffer,它会先发到缓冲区里面,然后由操作系统去调度发送。所以,send 返回成功,仅仅只是说明,数据放到缓冲区成功了,不代表对端接收了,更不代表对端应用程序正确处理了。所以我们会看到缓冲区不满的时候,send 函数很快就返回了,而缓冲区满的时候,send 函数会阻塞直到超时返回错误。recv 函数同理,实际上是从缓冲区获取数据,发过来的网络数据,系统将会放到缓冲区里面,直到 recv 函数去获取数据,才取出来,并且释放出空间。稍后我们通过实例来看这些缓冲区。

如何查看 Socket 缓冲区

Linux 下面查看 Socket 的缓冲区情况非常的简单,就是用 netstat -an 命令,它会列出所有的连接的端口,我们看一下实例

在这里插入图片描述

这里就指出每个 Active 的连接,主要的元素包括 Proto 协议,上图是 UDP 协议,然后是 RecvQ 和 SendQ,这就是本文讨论的 Socket 缓冲区,一个是接收缓冲,一个是发送缓冲,我们可以实时查看当前的状态。后面是本机 IP 和端口,以及对端的 IP 和端口,最后是连接状态,上图是 UDP 的所有没有状态。

下面我们运行一个 Socket 程序,再看 netstat 状态,来感受一下,