一文带你搞定TCP连接队列 tcp协议接口对接

TCP握手的时候维护的队列

  • 半连接队列(SYN队列)
  • 全连接队列(accepted队列)

半连接队列是什么?

服务器收到客户端SYN数据包后,Linux内核会把该连接存储到半连接队列中,并响应SYN+ACK报文给客户端。

全连接队列是什么?

服务器在收到客户端第三次握手的ACK报文后,内核会把该连接从半连接队列中移除,然后创建一个新的完全的连接并将其放入全连接队列中,等待应用程序调用accept函数把连接取走。

队列溢出会有啥问题?

半连接和全连接队列都有最大长度限制,超过限制时,内核会直接丢弃,返回RST报文。

如何查看全连接队列?

# -l 显示正在listening的socket
# -n 不解析服务名称
# -t 只显示tcp socket
ss -lnt

Recv-Q/Send-Q在Listen状态和非Listen状态下代表的含义不一样。

在Listen状态下:

  • Recv-Q:当前全连接队列的大小,完成三次握手等待accept的TCP连接
  • Send-Q:全连接队列的最大长度,上图中表示80端口的TCP服务全连接队列的最大长度为128。

在非Listen状态下:

  • Recv-Q:已收到但未被应用程序读取的字节数
  • Send-Q:已发送但未收到确认的字节数

如何查看TCP全连接队列溢出情况?

netstat -s | grep overflowed

通过上图可以看出,全连接队列一共溢出了1910次,如果这个数字在某个时间段一直增加,说明该时间段的全连接队列已经满载溢出。

全连接队列溢出后的情况?

全连接队列溢出后的处理受内核参数tcp_abort_on_overflow控制:

# 通过以下命令可以看出默认值是0
cat /proc/sys/net/ipv4/tcp_abort_on_overflow
  • 0:如果全连接队列满了,服务端会直接丢弃客户端发送过来的ACK数据包
  • 1:如果全连接队列满了,服务端会发送一个reset包给客户端,表示废弃这个握手过程和连接

假设服务端将tcp_abort_on_overflow设置为1,在服务端全连接队列满载以后,客户端如果还在不停的发起连接将会收到connection reset by peer的错误。

tcp_abort_on_overflow设置为0更有利于应对突发流量。

如何增加TCP全连接队列?

TCP全连接队列的最大值取决于somaxconn和blacklog之间的最小值:

  • somaxconn:linux内核参数,可以通过/proc/sys/net/core/somaxconn修改其值
  • backlog:listen(int sockfd, int backlog)函数中的backlog大小,一般应用程序都可以自定义该值

如何查看TCP半连接队列长度?

# 执行以下命令就可以查看半连接队列的大小
netstat -natp | grep SYN_RECV | wc -l

如何查看TCP半连接队列溢出的情况?

netstat -s | grep 'SYNs to LISTEN'

上图中我们可以看出半连接队列累计一共丢弃了220418个TCP连接,如果多次执行该命令该值有上升趋势,说明当前时间段存在半连接队列溢出现象。

半连接队列大小受哪些条件影响?

半连接队列的大小受内核参数tcp_max_syn_backlog控制,但是该值不一定是半连接队列的最大值(在较新版本的linux内核中理论上半连接队列的最大值是全连接队列的最大值),队列的溢出是有一定条件的:

  • 如果半连接队列满了,并且没有开启tcp_syncookies,就会丢弃连接
  • 如果全连接队列满了,并且没有重传SYN+ACK包的连接请求多余1个,也会丢弃连接
  • 如果没有开启tcp_syncookies,并且tcp_max_syn_backlog减去当前半连接队列长度小于(tcp_max_syn_backlog >> 2),则会丢弃连接

什么是syncookies?

syncookies是服务器根据当前状态计算一个值,然后再SYN+ACK报文中发出,当客户端返回ACK报文时,服务端取出该值进行验证,验证成功则认为连接建立成功。

开启syncookies功能可以在不使用半连接队列的情况下成功建立连接。

如何设置syncookies的值?

通过内核tcp_syncookies参数进行控制:

# 可以查看tcp_syncookies的值
cat /proc/sys/net/ipv4/tcp_syncookies

tcp_syncookies不同的值分别为不同的含义:

  • 0:表示关闭tcp_syncookies功能
  • 1:只有当半连接队列满时再启用tcp_syncookies功能
  • 2:表示无条件开启tcp_syncookies功能

如何抵御SYN攻击?

SYN攻击是指对服务端一直发送SYN包,但不回第三次握手的ACK数据包,此时会导致服务端有大量的SYN_RECV的TCP连接。

抵御SYN攻击可以采取以下方法:

  • 增大半连接队列
  • 开启tcp_syncookies功能
  • 减少SYN+ACK的重传次数

相关文章

3000字讲讲TCP协议,握手挥手不是你想的那么简单

专注于Java领域优质技术,欢迎关注作者: tobe 来自:tobe的呓语上一次讲了 UDP 协议,从这次开始,就要讲 TCP 协议了,因为 TCP 协议涉及到的东西很多,一篇文章概括不完,所以我把...

Java编程-TCP JAVA编程手机软件

1.1. Java的TCP面向连接, 数据安全, 区分服务器端和客户端.TCP分为Socket(客户端)和ServerSocket(服务端)需要分别建立客户端和服务器端客户端和服务端建立连接后,通过S...

Java网络编程---TCP通信 java的tcp通讯协议数据传输

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信Java对基于TCP协议的网...

4000 字详解TCP超时与重传,看完没收获算我输

专注于Java领域优质技术,欢迎关注作者: tobe 来自:tobe的呓语上一篇介绍 TCP 的文章「TCP 三次握手,四次挥手和一些细节」反馈还不错,还是蛮开心的,这次接着讲一讲关于超时和重传那一部...

用 Wireshark 让你看见 TCP 到底是什么样

前言当你看到这篇文章时,你只能看到已经渲染好的文字和图像,而网络数据的交互对我们来说,却是看不见的,所以学习计算机网络原理的时候就会觉得非常的抽象,这一度让我苦恼。而且网络数据交换真实的模样,到底是不...

一文带你搞定TCP流量控制 tcp流量控制算法

摘要理想的流量控制实际的流量控制窗口关闭糊涂窗口综合征理想的流量控制什么是流量控制?流量控制就是发送方不能无脑的给接收方发送数据,它需要根据接收方的处理能力来发送数据。理想下的流量控制?理想意味着在实...