成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易版 netstat 命令

開(kāi)發(fā) 后端
netstat 使用 go 語(yǔ)言實(shí)現(xiàn)是什么操作?本文從 netstat 原理出發(fā)詳細(xì)解讀了這一實(shí)踐。

  netstat 使用 go 語(yǔ)言實(shí)現(xiàn)是什么操作?本文從 netstat 原理出發(fā)詳細(xì)解讀了這一實(shí)踐。

netstat 工作原理

netstat 命令是 linux 系統(tǒng)中查看網(wǎng)絡(luò)情況的一個(gè)命令。比如我們可以通過(guò)netstat \-ntlp | grep 8080查看監(jiān)聽(tīng) 8080 端口的進(jìn)程。

netstat 工作原理如下:

  1.  通過(guò)讀取/proc/net/tcp 、/proc/net/tcp6 文件,獲取 socket 本地地址,本地端口,遠(yuǎn)程地址,遠(yuǎn)程端口,狀態(tài),inode 等信息
  2.  接著掃描所有/proc/[pid]/fd 目錄下的的 socket 文件描述符,建立 inode 到進(jìn)程 pid 映射
  3.  根據(jù) pid 讀取/proc/[pid]/cmdline 文件,獲取進(jìn)程命令和啟動(dòng)參數(shù)
  4.  根據(jù) 2,3 步驟,即可以獲得 1 中對(duì)應(yīng) socket 的相關(guān)進(jìn)程信息

我們可以做個(gè)測(cè)試驗(yàn)證整個(gè)流程。先使用 nc 命令監(jiān)聽(tīng) 8090 端口: 

  1. nc -l 8090 

找到上面 nc 進(jìn)程的 pid,查看該進(jìn)程所有打開(kāi)的文件描述符: 

  1. vagrant@vagrant:/proc/25556/fd$ ls -alh  
  2. total 0  
  3. dr-x------ 2 vagrant vagrant  0 Nov 18 12:21 .  
  4. dr-xr-xr-x 9 vagrant vagrant  0 Nov 18 12:20 ..  
  5. lrwx------ 1 vagrant vagrant 64 Nov 18 12:21 0 -> /dev/pts/1  
  6. lrwx------ 1 vagrant vagrant 64 Nov 18 12:21 1 -> /dev/pts/1  
  7. lrwx------ 1 vagrant vagrant 64 Nov 18 12:21 2 -> /dev/pts/1  
  8. lrwx------ 1 vagrant vagrant 64 Nov 18 12:21 3 -> socket:[2226056] 

上面列出的所有文件描述中,socket:[2226056]為 nc 命令監(jiān)聽(tīng) 8090 端口所創(chuàng)建的 socket。其中2226056為該 socket 的 inode。

根據(jù)該 inode 號(hào),我們查看/proc/net/tcp對(duì)應(yīng)的記錄信息,其中1F9A為本地端口號(hào),轉(zhuǎn)換成十進(jìn)制恰好為 8090: 

  1. vagrant@vagrant:/proc/25556/fd$ cat /proc/net/tcp | grep 2226056  
  2.    1: 00000000:1F9A 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 2226056 1 0000000000000000 100 0 0 10 0 

根據(jù)進(jìn)程 id,我們查看進(jìn)程名稱和啟動(dòng)參數(shù): 

  1. vagrant@vagrant:/proc/25556/fd$ cat /proc/25556/cmdline  
  2. nc-l8090 

下面我們看下/proc/net/tcp文件格式。

/proc/net/tcp 文件格式

/proc/net/tcp文件首先會(huì)列出所有監(jiān)聽(tīng)狀態(tài)的 TCP 套接字,然后列出所有已建立的 TCP 套接字。我們通過(guò)head \-n 5 /proc/net/tcp命令查看該文件頭五行: 

  1. sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode  
  2.    0: 0100007F:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 22279 1 0000000000000000 100 0 0 10 0  
  3.    1: 00000000:1FBB 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 21205 1 0000000000000000 100 0 0 10 0  
  4.    2: 00000000:26FB 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 21203 1 0000000000000000 100 0 0 10 0  
  5.    3: 00000000:26FD 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 21201 1 0000000000000000 100 0 0 10 0 

每一行各個(gè)字段解釋說(shuō)明如下,由于太長(zhǎng)分為三部分說(shuō)明:

第一部分: 

  1. 46: 010310AC:9C4C 030310AC:1770 01   
  2. |      |      |      |      |   |--> 連接狀態(tài),16 進(jìn)制表示,具體值見(jiàn)下面說(shuō)明  
  3. |      |      |      |      |------> 遠(yuǎn)程 TCP 端口號(hào),主機(jī)字節(jié)序,16 進(jìn)制表示  
  4. |      |      |      |-------------> 遠(yuǎn)程 IPv4 地址,網(wǎng)絡(luò)字節(jié)序,16 進(jìn)制表示  
  5. |      |      |--------------------> 本地 TCP 端口號(hào),主機(jī)字節(jié)序,16 進(jìn)制表示  
  6. |      |---------------------------> 本地 IPv4 地址,網(wǎng)絡(luò)字節(jié)序,16 進(jìn)制表示  
  7. |----------------------------------> 條目編號(hào),從 0 開(kāi)始 

上面連接狀態(tài)所有值如下,具體參見(jiàn) linux 源碼 tcp\_states.h[1]: 

  1. enum {  
  2.  TCP_ESTABLISHED = 1 
  3.  TCP_SYN_SENT,  
  4.  TCP_SYN_RECV,  
  5.  TCP_FIN_WAIT1,  
  6.  TCP_FIN_WAIT2,  
  7.  TCP_TIME_WAIT,  
  8.  TCP_CLOSE,  
  9.  TCP_CLOSE_WAIT,  
  10.  TCP_LAST_ACK,  
  11.  TCP_LISTEN,  
  12.  TCP_CLOSING, /* Now a valid state */  
  13.  TCP_NEW_SYN_RECV,  
  14.  TCP_MAX_STATES /* Leave at the end! */  
  15. }; 

第二部分: 

  1. 00000150:00000000 01:00000019 00000000    
  2.       |        |     |     |       |--> number of unrecovered RTO timeouts  
  3.       |        |     |     |----------> number of jiffies until timer expires  
  4.       |        |     |----------------> timer_active,具體值見(jiàn)下面說(shuō)明  
  5.       |        |----------------------> receive-queue,當(dāng)狀態(tài)是 ESTABLISHED,表示接收隊(duì)列中數(shù)據(jù)長(zhǎng)度;狀態(tài)是 LISTEN,表示已經(jīng)完成連接隊(duì)列的長(zhǎng)度  
  6.       |-------------------------------> transmit-queue,發(fā)送隊(duì)列中數(shù)據(jù)長(zhǎng)度 

timer_active 所有值與說(shuō)明如下:

  •  0 no timer is pending
  •  1 retransmit-timer is pending
  •  2 another timer (e.g. delayed ack or keepalive) is pending
  •  3 this is a socket in TIME_WAIT state. Not all fields will contain data (or even exist)
  •  4 zero window probe timer is pending

第三部分: 

  1. 1000        0 54165785 4 cd1e6040 25 4 27 3 -1  
  2.    |          |    |     |    |     |  | |  | |--> slow start size threshold,   
  3.    |          |    |     |    |     |  | |  |      or -1 if the threshold  
  4.    |          |    |     |    |     |  | |  |      is >= 0xFFFF  
  5.    |          |    |     |    |     |  | |  |----> sending congestion window  
  6.    |          |    |     |    |     |  | |-------> (ack.quick<<1)|ack.pingpong  
  7.    |          |    |     |    |     |  |---------> Predicted tick of soft clock  
  8.    |          |    |     |    |     |              (delayed ACK control data)  
  9.    |          |    |     |    |     |------------> retransmit timeout  
  10.    |          |    |     |    |------------------> location of socket in memory  
  11.    |          |    |     |-----------------------> socket reference count  
  12.    |          |    |-----------------------------> socket 的 inode 號(hào)  
  13.    |          |----------------------------------> unanswered 0-window probes 
  14.    |---------------------------------------------> socket 所屬用戶的 uid 

Go 實(shí)現(xiàn)簡(jiǎn)易版本 netstat 命令

netstat 工作原理和/proc/net/tcp文件結(jié)構(gòu),我們都已經(jīng)了解了,現(xiàn)在可以使用據(jù)此使用 Go 實(shí)現(xiàn)一個(gè)簡(jiǎn)單版本的 netstat 命令。

核心代碼如下,完整代碼參加 go-netstat[2]: 

  1. // 狀態(tài)碼值  
  2. const (  
  3.  TCP_ESTABLISHED = iota + 1  
  4.  TCP_SYN_SENT  
  5.  TCP_SYN_RECV  
  6.  TCP_FIN_WAIT1  
  7.  TCP_FIN_WAIT2 
  8.  TCP_TIME_WAIT  
  9.  TCP_CLOSE  
  10.  TCP_CLOSE_WAIT  
  11.  TCP_LAST_ACK  
  12.  TCP_LISTEN  
  13.  TCP_CLOSING  
  14.  //TCP_NEW_SYN_RECV  
  15.  //TCP_MAX_STATES  
  16.  
  17. // 狀態(tài)碼  
  18. var states = map[int]string{  
  19.  TCP_ESTABLISHED: "ESTABLISHED",  
  20.  TCP_SYN_SENT:    "SYN_SENT",  
  21.  TCP_SYN_RECV:    "SYN_RECV",  
  22.  TCP_FIN_WAIT1:   "FIN_WAIT1",  
  23.  TCP_FIN_WAIT2:   "FIN_WAIT2",  
  24.  TCP_TIME_WAIT:   "TIME_WAIT",  
  25.  TCP_CLOSE:       "CLOSE",  
  26.  TCP_CLOSE_WAIT:  "CLOSE_WAIT",  
  27.  TCP_LAST_ACK:    "LAST_ACK",  
  28.  TCP_LISTEN:      "LISTEN",  
  29.  TCP_CLOSING:     "CLOSING",  
  30.  //TCP_NEW_SYN_RECV: "NEW_SYN_RECV",  
  31.  //TCP_MAX_STATES:   "MAX_STATES",  
  32.  
  33. // socketEntry 結(jié)構(gòu)體,用來(lái)存儲(chǔ)/proc/net/tcp 每一行解析后數(shù)據(jù)信息  
  34. type socketEntry struct {  
  35.  id      int  
  36.  srcIP   net.IP  
  37.  srcPort int  
  38.  dstIP   net.IP  
  39.  dstPort int  
  40.  state   string  
  41.  txQueue       int  
  42.  rxQueue       int  
  43.  timer         int8  
  44.  timerDuration time.Duration  
  45.  rto           time.Duration // retransmission timeout  
  46.  uid           int  
  47.  uname         string  
  48.  timeout       time.Duration  
  49.  inode         string  
  50.  
  51. // 解析/proc/net/tcp 行記錄  
  52. func parseRawSocketEntry(entry string) (*socketEntry, error) {  
  53.  se := &socketEntry{} 
  54.  entrys :strings.Split(strings.TrimSpace(entry), " ")  
  55.  entryItems :make([]string, 0, 17)  
  56.  for _, ent :range entrys {  
  57.   if ent == "" {  
  58.    continue  
  59.   }  
  60.   entryItems = append(entryItems, ent)  
  61.  }  
  62.  id, err :strconv.Atoi(string(entryItems[0][:len(entryItems[0])-1]))  
  63.  if err != nil {  
  64.   return nil, err  
  65.  }  
  66.  se.id = id                                     // sockect entry id  
  67.  localAddr :strings.Split(entryItems[1], ":") // 本地 ip  
  68.  se.srcIP = parseHexBigEndianIPStr(localAddr[0])  
  69.  port, err :strconv.ParseInt(localAddr[1], 16, 32) // 本地 port  
  70.  if err != nil {  
  71.   return nil, err  
  72.  }  
  73.  se.srcPort = int(port)  
  74.  remoteAddr :strings.Split(entryItems[2], ":") // 遠(yuǎn)程 ip  
  75.  se.dstIP = parseHexBigEndianIPStr(remoteAddr[0])  
  76.  port, err = strconv.ParseInt(remoteAddr[1], 16, 32) // 遠(yuǎn)程 port  
  77.  if err != nil { 
  78.   return nil, err  
  79.  }  
  80.  se.dstPort = int(port)  
  81.  state, _ :strconv.ParseInt(entryItems[3], 16, 32) // socket 狀態(tài)  
  82.  se.state = states[int(state)] 
  83.  tcpQueue :strings.Split(entryItems[4], ":")  
  84.  tQueue, err :strconv.ParseInt(tcpQueue[0], 16, 32) // 發(fā)送隊(duì)列數(shù)據(jù)長(zhǎng)度  
  85.  if err != nil {  
  86.   return nil, err  
  87.  }  
  88.  se.txQueue = int(tQueue)  
  89.  sQueue, err :strconv.ParseInt(tcpQueue[1], 16, 32) // 接收隊(duì)列數(shù)據(jù)長(zhǎng)度  
  90.  if err != nil {  
  91.   return nil, err  
  92.  }  
  93.  se.rxQueue = int(sQueue)   
  94.  se.uid, err = strconv.Atoi(entryItems[7]) // socket uid  
  95.  if err != nil {  
  96.   return nil, err  
  97.  }  
  98.  se.uname = systemUsers[entryItems[7]] // socket user name 
  99.  se.inode = entryItems[9]              // socket inode  
  100.  return se, nil  
  101. // hexIP 是網(wǎng)絡(luò)字節(jié)序/大端法轉(zhuǎn)換成的 16 進(jìn)制的字符串  
  102. func parseHexBigEndianIPStr(hexIP string) net.IP {  
  103.  b := []byte(hexIP)  
  104.  for i, j :1, len(b)-2; i < j; i, j = i+2, j-2 { // 反轉(zhuǎn)字節(jié),轉(zhuǎn)換成小端法  
  105.   b[i], b[i-1], b[j], b[j+1] = b[j+1], b[j], b[i-1], b[i]  
  106.  }  
  107.  l, _ :strconv.ParseInt(string(b), 16, 64)  
  108.  return net.IPv4(byte(l>>24), byte(l>>16), byte(l>>8), byte(l))  
  109.  

 

責(zé)任編輯:龐桂玉 來(lái)源: 馬哥Linux運(yùn)維
相關(guān)推薦

2023-12-29 08:31:49

Spring框架模塊

2022-11-01 18:29:25

Go語(yǔ)言排序算法

2020-08-12 08:56:30

代碼凱撒密碼函數(shù)

2023-05-08 07:55:05

快速排序Go 語(yǔ)言

2024-08-29 13:23:04

WindowsGo語(yǔ)言

2012-03-13 10:40:58

Google Go

2022-05-19 14:14:26

go語(yǔ)言限流算法

2022-02-11 13:44:56

fiber架構(gòu)React

2012-08-06 08:50:05

Go語(yǔ)言

2024-06-06 09:47:56

2017-01-13 08:37:57

PythonAlphaGoMuGo

2023-03-27 00:20:48

2022-04-18 10:01:07

Go 語(yǔ)言漢諾塔游戲

2023-07-31 08:01:13

二叉搜索測(cè)試

2021-07-26 09:47:38

Go語(yǔ)言C++

2022-10-20 11:49:49

JS動(dòng)畫幀,CSS

2011-12-05 10:37:53

Linux服務(wù)器Shell腳本

2021-03-01 21:59:25

編程語(yǔ)言GoCX

2021-03-01 18:35:18

Go語(yǔ)言虛擬機(jī)

2022-07-20 09:52:44

Go語(yǔ)言短信驗(yàn)證碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美精品一区在线发布 | 激情久久av一区av二区av三区 | 亚洲第一视频 | 精品成人av | 蜜臀久久 | 91视视频在线观看入口直接观看 | 中文av字幕| 美女视频h| 一本一道久久a久久精品综合 | 久久伊人免费视频 | 91p在线观看 | 欧美成人精品一区二区男人看 | 日韩在线91 | 精品成人av | 免费美女网站 | 欧美jizzhd精品欧美巨大免费 | 人人玩人人干 | 久久久久电影 | 草草草草视频 | 日本不卡免费新一二三区 | 欧美一级二级视频 | 天堂视频一区 | 亚洲成人精品一区 | 国产精品久久网 | 中文日本在线 | 成人免费观看男女羞羞视频 | 我想看一级黄色毛片 | 国产日韩欧美在线 | 国产精品高清在线 | 日韩有码在线观看 | 波霸ol一区二区 | 九九国产| 久久久久久亚洲精品 | 国产亚洲精品91 | 91精品免费视频 | 久久精品二区 | 亚洲一区二区三区桃乃木香奈 | 精品一区二区三区不卡 | 亚洲小视频在线播放 | 拍戏被cao翻了h承欢 | 午夜天堂|