
Socket 就是发送和接收网络数据,Socket 有发送缓冲也有接收缓冲,这些缓冲区有什么作用?
1、什么是Socket缓冲区?
熟悉 Socket 的读者都知道,Socket 的发送和接收,就是调用 send 和 recv 函数。
实际操作中,我们将要发送的数据 buffer,送给 send 函数,然后 send 就会返回成功或者失败,那么,send 什么时候返回成功呢?是发送到对端函数才返回吗?答案是否定的。(注意:Socket 有同步和异步,本文主要讨论 Socket 缓冲区,不深究异步,都假定是同步)
实际上呢,Socket 有一个缓冲区,send 的数据 buffer,它会先发到缓冲区里面,然后由操作系统去调度发送。所以,send 返回成功,仅仅只是说明,数据放到缓冲区成功了,不代表对端接收了,更不代表对端应用程序正确处理了。所以我们会看到缓冲区不满的时候,send 函数很快就返回了,而缓冲区满的时候,send 函数会阻塞直到超时返回错误。recv 函数同理,实际上是从缓冲区获取数据,发过来的网络数据,系统将会放到缓冲区里面,直到 recv 函数去获取数据,才取出来,并且释放出空间。稍后我们通过实例来看这些缓冲区。
2、如何查看socket的缓冲区?
Linux 下面查看 Socket 的缓冲区情况非常的简单,就是用 netstat -an
命令,它会列出所有的连接的端口,我们看一下实例
这里就指出每个 Active 的连接,主要的元素包括 Proto 协议,上图是 UDP 协议,然后是 RecvQ 和 SendQ,这就是本文讨论的 Socket 缓冲区,一个是接收缓冲,一个是发送缓冲,我们可以实时查看当前的状态。后面是本机 IP 和端口,以及对端的 IP 和端口,最后是连接状态,上图是 UDP 的所有没有状态。
下面我们运行一个 Socket 程序,再看 netstat 状态,来感受一下,
这个时候我们发现,出现了一个 TCP 的连接,是 SYN 状态,SendQ 是 1,因为发送了一个 syn 包到缓冲区,对端一直连接不上(服务端没开启),所以缓冲区一直是 1。若我们开启服务器端,连接会正常,这时候你再观察,会发现 SendQ 变成 0,我们看一下:
这时候连接建立了,缓冲区变成 0 了。
3、网络数据发送和接收与缓冲区的关系
通过以上的分析,我们应该已经大致了解了网络数据发送和接收与缓冲区的关系。
总的来说,不管发送还是接收,都要先经过缓冲区,操作系统将会处理缓冲区里面的数据。以发送为例,应用程序提交到缓冲区,就等着系统来处理了,网络不畅通,系统就发不出去,缓冲就会越积越多;接收也是同样情况,系统接收到数据,放缓冲区里面,通知应用程序来获取,应用程序若不及时处理,缓冲就越积越多。
所以缓冲区的大小多少合适呢?
系统给了一个默认值,但是不见得适合所有情况,高速网络可以调大,低速网络可以调小,这个应用程序可以自行灵活控制。


关注琉忆编程库,一起学编程

