golang解析linux /proc/net/tcp /proc/net/tcp6文件中的IP地址

直接上代码
package main

import (
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"net"
	"strconv"
	"strings"
)

func hexToByte(s byte) (byte, error) {
    if s <= '9' && s >= '0' {
        return s-'0', nil
    } else if s >= 'a' && s <= 'f' {
        return s-'a'+10, nil
    } else if s >= 'A' && s <= 'F' {
        return s-'A'+10, nil
    } else {
        return s, errors.New("invalid byte")
    }
}

// cat /proc/net/tcp6:
// sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
// 36: 0000000000000000FFFF000032190A0A:1F96 0000000000000000FFFF000032190A0A:4F5F 01 00000000:00000000 00:00000000 00000000 0   0       1245464177 2  ffff8e714244d500 21 4 22 10 7
// AnalysisIpv6 可将上面的16进制的ipv6地址转为可识别的ipv6格式:例如“::ffff:10.10.25.50:48422”
func AnalysisIpv6(s string) (string, error) {
    hexIP := s[:len(s)-5]
    hexPort := s[len(s)-4:]
    if hexIP == "00000000000000000000000000000000" {
    	// 忽略0.0.0.0
    	return "", nil
    }
    b := make(net.IP, 16)
    for i:=0; i< 4; i++ {
        for j :=0; j<4; j ++ {
            srcIndex := i *4 +3 -j
            targetIndex := i *4 + j
            c, err := hexToByte(hexIP[srcIndex*2])
            if err != nil {
                return "", err
            }
            d, err := hexToByte(hexIP[srcIndex*2+1])
            if err != nil {
                return "", err
            }
            b[targetIndex] = c*16 + d
        }
    }
    ip := b.String()
    l := strings.Split(ip, ".")
    if len(l) > 2 {
        // 判断是否是真的ipv6格式, 如果不是则转为ipv6格式
        ip = "::ffff:" + ip
    }
    port, err := strconv.ParseUint(hexPort, 16, 16)
    return fmt.Sprintf("%s:%d", ip, port), err
}

// AnalysisIpv4 16进制的ipv4地址转为可识别的ipv4格式:例如“10.10.25.50:8888”
func AnalysisIpv4(s string) (string, error) {
    hexIP := s[:len(s)-5]
    hexPort := s[len(s)-4:]
    bytesIP, err := hex.DecodeString(hexIP)
    if err != nil {
        return "", nil
    }
    uint32IP := binary.LittleEndian.Uint32(bytesIP) //转换为主机字节序
    IP := make(net.IP, 4)
    binary.BigEndian.PutUint32(IP, uint32IP)
    port, err := strconv.ParseUint(hexPort, 16, 16)
    return fmt.Sprintf("%s:%d", IP.String(), port), err
}

func main() {
    strIpv6 := "0000000000000000FFFF000032190A0A:3D2D"
    fmt.Println(AnalysisIpv6(strIpv6))
    strIpv6 = "000080FE00000000FF5D1502020400FE:3D2D"
    fmt.Println(AnalysisIpv6(strIpv6))
    strIpv4 := "34190A0A:3D2D"
    fmt.Println(AnalysisIpv4(strIpv4))
}

上面代码输出结果:

::ffff:10.10.25.50:15661 <nil>
fe80::215:5dff:fe00:402:15661 <nil>
10.10.25.52:15661 <nil>

结果与 ss -nt 命令看到的IP地址相同.

发布了11 篇原创文章 · 获赞 1 · 访问量 2206

猜你喜欢

转载自blog.csdn.net/weixin_42450836/article/details/104801131