Go 学习 - netstat 基础

通过 /proc/net 下的文件读取 IP:PORT 信息,同时获取到相应的 socketid 值,从 /proc/pid/fd 中寻找 socketid 值,找到对应 pid 的值。

package main

import (
    "bufio"
    "bytes"
    "errors"
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "strconv"
    "strings"
)

const (
    PROC_NET_TCP = "/proc/net/tcp"
)

type NetStat struct {
    LocalAddree  string
    LocalPort    string
    RemoteAddree string
    RemotePort   string
    SocketID     string
}

func IpIntToString(ipInt string) string {
    ipInt2, _ := strconv.ParseInt(ipInt, 16, 0)
    ipSegs := make([]string, 4)
    var len int = len(ipSegs)
    buffer := bytes.NewBufferString("")
    for i := len - 1; i >= 0; i-- {
        tempInt := ipInt2 & 0xFF
        ipSegs[len-i-1] = strconv.FormatInt(tempInt, 10)
        ipInt2 = ipInt2 >> 8
    }
    for i := 0; i < len; i++ {
        buffer.WriteString(ipSegs[i])
        if i < len-1 {
            buffer.WriteString(".")
        }
    }
    return buffer.String()
}
func PortToString(portInt string) string {
    n, err := strconv.ParseInt(portInt, 16, 0)
    if err != nil {
        fmt.Println(err)
        return ""
    }
    port := strconv.FormatInt(n, 10)
    return port
}
func GetPIDBySocketID() ([]map[string]string, error) {
    socketList := []map[string]string{}
    // socketID = "socket:[" + socketID + "]"
    dirProcList, err := ioutil.ReadDir("/proc")
    if err != nil {
        return []map[string]string{}, err
    }
    for _, dirProc := range dirProcList {
        _, err := strconv.Atoi(dirProc.Name())
        if err != nil {
            continue
        }
        pidFD := fmt.Sprintf("/proc/%s/fd", dirProc.Name())
        dirPIDFdList, err := ioutil.ReadDir(pidFD)
        for _, dirPIDFd := range dirPIDFdList {
            socket := fmt.Sprintf("/proc/%s/fd/%s", dirProc.Name(), dirPIDFd.Name())
            data, err := os.Readlink(socket)
            if err != nil {
                continue
            }
            socketList = append(socketList, map[string]string{dirProc.Name(): data})
        }
    }
    return socketList, nil
}
func main() {
    netList := []NetStat{}
    netFd, err := os.Open(PROC_NET_TCP)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer netFd.Close()
    br := bufio.NewReader(netFd)
    for {
        line, _, c := br.ReadLine()
        if c == io.EOF {
            break
        }
        Info := strings.Fields(string(line))
        if len(strings.Split(Info[1], ":")) == 2 && len(strings.Split(Info[2], ":")) == 2 {
            net := NetStat{}
            net.LocalAddree = IpIntToString(strings.Split(Info[1], ":")[0])
            net.LocalPort = PortToString(strings.Split(Info[1], ":")[1])
            net.RemoteAddree = IpIntToString(strings.Split(Info[2], ":")[0])
            net.RemotePort = PortToString(strings.Split(Info[2], ":")[1])
            net.SocketID = Info[9]
            netList = append(netList, net)
        }
    }
    fmt.Println("localaddree    remoteaddree    socketid    pid")
    socketList, _ := GetPIDBySocketID()
    for _, n := range netList {
        pid := "--"
        for _, d := range socketList {
            for k, v := range d {
                if "socket:["+n.SocketID+"]" == v {
                    pid = k
                }
            }
        }
        fmt.Printf("%s    %s    %s    %s\n", n.LocalAddree+":"+n.LocalPort, n.RemoteAddree+":"+n.RemotePort, n.SocketID, pid)
    }
}