netstat

netstat是Linux系统中常用的用来测试网络程序和定位网络问题。在介绍netstat之前有必要介绍一下TCP相关的知识。

TCP

TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。

TCP提供了一种可靠、面向连接、字节流、传输层的服务,采用3次握手(three-way handshake)建立一个连接。采用4次挥手(four-way handshake)来关闭一个连接。

TCP为应用层提供全双工(full-duplex)服务,这意味着数据能在两个方向独立地进行传输。面向连接的TCP协议要求每次peer间通信前建立一条TCP连接,该连接可抽象为一个4元组(quadruple/four-tuple,有时也称socket pair):(local_ip, local_port, remote_ip, remote_port),这4个元素唯一地代表一条TCP连接。如图所示TCP header信息,图片来自维基百科。

TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果有必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的次序交给应用层。

状态转换图

详细的介绍可以阅读参考链接,介绍的通俗易懂。以下图片也来自参考链接。



文中介绍的比较详细:

  1. 三次握手主要是为了确认客户端和服务端的接收能力发送能力均是正常的。如果少了某一次就无法确定服务端或者客户端都是正常的。
  2. 同时,三次握手的一个重要功能是客户端和服务端交换ISN(Initial Sequence Number), 以便让对方知道接下来接收数据的时候如何按序列号组装数据。
  3. 而且通过三次握手商定各自的MSS(Maximum Segment Size),timestamp等参数。
TCP state transition diagram

注意

  1. TCP连接的任意一方均可以首先调用close()以发起主动关闭,并不是只有client能发起主动关闭。
  2. 从TCP状态转换图可知,只有首先调用close()发起主动关闭的一方才会进入TIME_WAIT状态,而且是必须进入(上图中左下角所示的3条状态迁移线最终均要进入该状态才能回到初始的CLOSED状态)。⚠️TIME_WAIT 只在主动关闭的一端出现。
  3. 进入TIME_WAIT状态的TCP连接需要经过2MSL才能回到初始CLOSED状态。因此TIME_WAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。

可以查看系统中time wait相关的配置信息。

tcp_max_tw_buckets: Maximal number of time wait sockets held by system simultaneously. If this number is exceeded TIME_WAIT socket is immediately destroyed and warning is printed. This limit exists only to prevent simple DoS attacks, you must not lower the limit artificially, but rather increase it (probably, after increasing installed memory), if network conditions require more than default value (180000).
tcp_tw_recycle: Enable fast recycling of sockets in TIME-WAIT status. The default value is 0 (disabled). It should not be changed without advice/request of technical experts.
tcp_tw_reuse: Allow to reuse TIME-WAIT sockets for new connections when it is safe from protocol viewpoint. The default value is 0. It should not be changed without advice/request of technical experts.

(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/ip_local_port_range
32768   60999
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
512
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_syn_retries
6
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_max_tw_buckets
65536
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_tw_recycle
0
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_tw_reuse
0
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_timestamps
1
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout
60
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_synack_retries
5
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_syncookies
1
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
512
(ENV) [root@ceph-2 ~]# cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0
(ENV) [root@ceph-2 ~]# dmesg | grep "TCP established hash table"
[    0.348520] TCP established hash table entries: 131072 (order: 8, 1048576 bytes)
(ENV) [root@ceph-2 ~]# dmesg | grep "TCP bind hash table"
[    0.348743] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)

为什么建立连接是三次握手,而关闭连接却是四次挥手呢?

这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方ACK和FIN一般都会分开发送。

TCB(Transmission Control Blocks)

由于每次连接会建立local端和remote端的四元组,每次连接都是唯一的,因此我们必须为每个连接维护单独的数据信息。TCP使用TCB来存储这些信息,TCB包含连接的重要信息,其中包括socket numbers,指向保存incoming和outgoing数据的缓冲区的指针,TCB还用于实现滑动窗口机制(sliding window mechanism)。同时记录和跟踪接收和确认的字节数,以及接收和尚未确认的字节数,当前窗口大小等。每个设备都维护自己的TCB用于连接。

A client process initiates a TCP connection by performing an active OPEN, sending a SYN message to a server. A server process using TCP prepares for an incoming connection request by performing a passive OPEN. Both devices create for each TCP session a data structure used to hold important data related to the connection, called a transmission control block (TCB).

netstat

  • -a:显示所有选项,默认不显示LISTEN相关,即为--all
  • -t:仅显示tcp相关选项
  • -u:仅显示udp相关选项
  • -n:拒绝显示别名,能显示数字的全部转化成数字,即为--numeric
  • -l:仅列出有在Listen(监听)的服务状态,即为--listening
  • -p:显示建立相关连接的程序名,即为--program
  • -r:显示路由信息,路由表,即为--route
  • -e:显示扩展信息,例如uid等,即为--extend
  • -s:按各个协议进行统计,即为--statistics
  • -c:每隔一个固定时间,执行该netstat命令,即为--continuous,默认是每隔一秒执行一次。
  • -i:显示网卡接口信息,也可以通过--interfaces=iface或者-I=iface来指定网卡。
  • -g: 显示多播组成员信息,即为--groups
  • -o: 显示网络定时器相关的信息,即为--timers

Note:

  1. LISTEN和LISTENING的状态只有用-a或者-l才能看到
  2. 默认情况下netstat会将输出结果中的Local AddressForeign Address中的主机名和端口号对应的应用都解析出来,导致耗时比较久。因此可以加上-n参数。

栗子

(ENV) [root@ceph-2 ~]# netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 10.255.101.74:2379      0.0.0.0:*               LISTEN      1927/etcd
tcp        0      0 10.255.101.74:2379      10.255.101.74:56724     ESTABLISHED 1927/etcd
tcp        0      0 127.0.0.1:5432          127.0.0.1:60822         ESTABLISHED 13954/postgres: dem
tcp        0      0 10.255.101.74:6801      10.255.101.74:34276     ESTABLISHED 2371/ceph-osd
tcp        0      0 10.255.101.74:56108     10.255.101.74:5433      TIME_WAIT   -
tcp        0      0 10.255.101.74:54792     10.255.101.75:8051      TIME_WAIT   -
tcp        0      0 10.255.101.74:59986     10.255.101.75:6806      ESTABLISHED 22813/xdcd
tcp        0      0 10.255.101.74:56832     10.255.101.74:5433      TIME_WAIT   -
tcp        0      0 10.255.101.74:58520     10.255.101.75:8051      ESTABLISHED 1591/prometheus
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  2      [ ACC ]     STREAM     LISTENING     12800257 22813/xdcd           /var/run/ceph/rbd-22813-775251968.asok
unix  2      [ ACC ]     STREAM     LISTENING     34574    2371/ceph-osd        /var/run/ceph/ceph-osd.1.asok
unix  2      [ ACC ]     STREAM     LISTENING     24053    1236/master          private/discard
unix  2      [ ACC ]     STREAM     LISTENING     13072154 22813/xdcd           /var/run/ceph/rbd-22813-787452928.asok
unix  2      [ ACC ]     STREAM     LISTENING     24056    1236/master          private/local
unix  3      [ ]         STREAM     CONNECTED     23369    383/systemd-journal  /run/systemd/journal/stdout
unix  2      [ ]         DGRAM                    6952     1/systemd            /run/systemd/shutdownd

可以看到输出结果保护两部分,Active Internet connections (servers and established)以及Active UNIX domain sockets (servers and established),分别为TCP链接和Unix域套接字。

统计TCP连接的情况

(ENV) [root@ceph-2 ~]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 497
TIME_WAIT 480

References

  • Transmission_Control_Protocol
  • “三次握手,四次挥手”你真的懂吗?
  • 简析TCP的三次握手与四次挥手
  • Linux netstat命令详解
  • TCPIP_State_Transition_Diagram(RFC793)
  • linux服务器大量TIME_WAIT状态问题
  • linux内核的tcp/ip协议栈分析
  • NAT网络下TCP连接建立时可能SYN包被服务器忽略-tcp_tw_recycle
  • linux tcp 大量 TIME_WAIT 问题
  • TCP Loop Connect
  • Coping with the TCP TIME-WAIT state on busy Linux servers

你可能感兴趣的:(netstat)