通过读文件,获取系统开放的端口

19 阅读8分钟

背景

最近在开发一个监控平台。无奈,要求去依赖(不能用 lsof或 netstat 等命令)。只能靠读取文件获取,所以写个文档记录下

实现

读取/proc/net/tcp & /proc/net/tcp6 , local_address 是本地的ip 和端口,端口是 16进制,需要自己转成10进制

$more  /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:75F9 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2684279959 1 0000000000000000 100 0 0 10 0                
   1: 0100007F:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 21610 1 0000000000000000 100 0 0 10 0                     
   2: 00000000:77DA 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 1878960781 1 0000000000000000 100 0 0 10 0                
   3: 00000000:EA3B 00000000:0000 0A 00000000:00000000 00:00000000 00000000    29        0 6509323 1 0000000000000000 100 0 0 10 0                   
   4: 68B3A30B:FDFC 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2946713631 1 0000000000000000 100 0 0 10 0                
   5: 0100007F:3D9C 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 60795 1 0000000000000000 100 0 0 10 0                     
   6: 00000000:7BBE 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 1878960775 1 0000000000000000 100 0 0 10 0                
   7: 0100007F:AB3F 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2822635099 1 0000000000000000 100 0 0 10 0                
   8: 0100007F:3DA0 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 147098039 1 0000000000000000 100 0 0 10 0                 
   9: 0100007F:4D41 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 147098040 1 0000000000000000 100 0 0 10 0                 
  10: 00000000:0801 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 6550767 1 0000000000000000 100 0 0 10 0                   
  11: 0100007F:6725 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2815996942 1 0000000000000000 100 0 0 10 0                
  12: 68B3A30B:4EC7 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2814904405 1 0000000000000000 100 0 0 10 0                
  13: 0100007F:5CA7 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2344334889 1 0000000000000000 100 0 0 10 0                
  14: 68B3A30B:FDE8 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2946713630 1 0000000000000000 100 0 0 10 0                
  15: 0100007F:2808 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2481402032 1 0000000000000000 100 0 0 10 0                
  16: 0100007F:2809 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2684261702 1 0000000000000000 100 0 0 10 0                
  17: 00000000:758A 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 2684279960 1 0000000000000000 100 0 0 10 0      

解释

part 1

   0: 00000000:75F9 00000000:0000 0A 
   |      |      |      |      |   |--> connection state(套接字状态)
   |      |      |      |      |------> remote TCP port number(远端端口,主机字节序)
   |      |      |      |-------------> remote IPv4 address(远端IP,网络字节序)
   |      |      |--------------------> local TCP port number(本地端口,主机字节序)
   |      |---------------------------> local IPv4 address(本地IP,网络字节序)
   |----------------------------------> number of entry

connection state(套接字状态),不同的数值代表不同的状态,参照如下:

TCP_ESTABLISHED:1   TCP_SYN_SENT:2
TCP_SYN_RECV:3      TCP_FIN_WAIT1:4
TCP_FIN_WAIT2:5     TCP_TIME_WAIT:6
TCP_CLOSE:7         TCP_CLOSE_WAIT:8
TCP_LAST_ACL:9      TCP_LISTEN:10
TCP_CLOSING:11

part 2

   00000000:00000000 00:00000000 00000000
      |        |     |     |       |--> number of unrecovered RTO timeouts(超时重传次数)
      |        |     |     |----------> number of jiffies until timer expires(超时时间,单位是jiffies)
      |        |     |----------------> timer_active (定时器类型,see below)
      |        |----------------------> receive-queue(根据状态不同有不同表示,see below)
      |-------------------------------> transmit-queue(发送队列中数据长度)

receive-queue,当状态是ESTABLISHED,表示接收队列中数据长度;状态是LISTEN,表示已经完成连接队列的长度 timer_active:

  0  no timer is pending  //没有启动定时器
  1  retransmit-timer is pending  //重传定时器
  2  another timer (e.g. delayed ack or keepalive) is pending  //连接定时器、FIN_WAIT_2定时器或TCP保活定时器
  3  this is a socket in TIME_WAIT state. Not all fields will contain data (or even exist)  //TIME_WAIT定时器
  4  zero window probe timer is pending  //持续定时器

part3

    0        0 2684279959 1 0000000000000000 100 0 0 10 0
    |          |    |     |    |              |  | |  | |--> slow start size threshold, 
	                                                or -1 if the threshold is >=0xFFFF 
    |          |    |     |    |              |  | |  |     (如果慢启动阈值大于等于0xFFFF则显示-1,否则表示慢启动阈值)
    |          |    |     |    |              |  | |  |      
    |          |    |     |    |              |  | |  |----> sending congestion window(当前拥塞窗口大小)
    |          |    |     |    |              |  | |-------> (ack.quick<<1)|ack.pingpong
	                                               (快速确认数和是否启用的标志位的或运算结果)    
    |          |    |     |    |              |  |---------> Predicted tick of soft clock (delayed ACK control data)
	                                               (用来计算延时确认的估值)
    |          |    |     |    |              |             
    |          |    |     |    |              |------------> retransmit timeout()(RTO,单位是clock_t)
    |          |    |     |    |------------------> location of socket in memory(socket实例的地址)
    |          |    |     |-----------------------> socket reference count(socket结构体的引用数)
    |          |    |-----------------------------> inode(套接字对应的inode)
    |          |----------------------------------> unanswered 0-window probes(see below)
    |---------------------------------------------> uid(用户id)

unanswered 0-window probes:持续定时器或保活定时器周期性发送出去但未被确认的TCP段数目,在收到ACK之后清零

原文章: Linux文件/proc/net/tcp分析