Windows 版本
package main
import (
"bytes"
"fmt"
"os/exec"
"regexp"
"strconv"
"strings"
)
// ConnectionInfo 存储连接信息
type ConnectionInfo struct {
Protocol string
LocalAddr string
RemoteAddr string
PID int
Path string
}
func main() {
conns, err := getConnections()
if err != nil {
fmt.Printf("Error getting connections: %v\n", err)
return
}
fmt.Println("Connections:")
for _, conn := range conns {
fmt.Printf("Protocol: %s, Local Address: %s, Remote Address: %s, PID: %d, Path: %s\n",
conn.Protocol, conn.LocalAddr, conn.RemoteAddr, conn.PID, conn.Path)
}
}
func getConnections() ([]ConnectionInfo, error) {
cmd := exec.Command("netstat", "-ano")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return nil, err
}
return parseNetstatOutput(out.String()), nil
}
func parseNetstatOutput(output string) []ConnectionInfo {
var connections []ConnectionInfo
lines := strings.Split(output, "\n")
re := regexp.MustCompile(`(?P<Proto>\S+)\s+(?P<LocalAddr>\S+)\s+(?P<RemoteAddr>\S+)\s+(?P<Pid>\d+)`)
for _, line := range lines {
if line == "" || strings.Contains(line, "Proto") {
continue // 跳过空行和标题行
}
matches := re.FindStringSubmatch(line)
if matches != nil {
pid, _ := strconv.Atoi(matches[4])
connections = append(connections, ConnectionInfo{
Protocol: matches[1],
LocalAddr: matches[2],
RemoteAddr: matches[3],
PID: pid,
Path: getProcessPath(pid),
})
}
}
return connections
}
func getProcessPath(pid int) string {
cmd := exec.Command("tasklist", "/fo", "csv", "/nh")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return "Unknown"
}
lines := strings.Split(out.String(), "\n")
for _, line := range lines {
if line == "" {
continue
}
// 解析 CSV 格式的输出
parts := strings.Split(line, "\",\"")
if len(parts) > 1 {
pidStr := strings.Trim(parts[1], "\"")
if pidStr == strconv.Itoa(pid) {
return strings.Trim(parts[0], "\"")
}
}
}
return "Unknown"
}
Linux 版本
package main
import (
"bytes"
"fmt"
"os/exec"
"regexp"
"strconv"
"strings"
)
// ConnectionInfo 存储连接信息
type ConnectionInfo struct {
Protocol string
LocalAddr string
RemoteAddr string
PID int
Path string
}
func main() {
udpConns, err := getConnections("udp")
if err != nil {
fmt.Printf("Error getting UDP connections: %v\n", err)
return
}
tcpConns, err := getConnections("tcp")
if err != nil {
fmt.Printf("Error getting TCP connections: %v\n", err)
return
}
fmt.Println("UDP Connections:")
for _, conn := range udpConns {
fmt.Printf("Protocol: %s, Local Address: %s, Remote Address: %s, PID: %d, Path: %s\n",
conn.Protocol, conn.LocalAddr, conn.RemoteAddr, conn.PID, conn.Path)
}
fmt.Println("\nTCP Connections:")
for _, conn := range tcpConns {
fmt.Printf("Protocol: %s, Local Address: %s, Remote Address: %s, PID: %d, Path: %s\n",
conn.Protocol, conn.LocalAddr, conn.RemoteAddr, conn.PID, conn.Path)
}
}
func getConnections(protocol string) ([]ConnectionInfo, error) {
var cmd *exec.Cmd
if protocol == "udp" {
cmd = exec.Command("ss", "-u", "-p", "-n")
} else {
cmd = exec.Command("ss", "-t", "-p", "-n")
}
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return nil, err
}
return parseSSOutput(out.String(), protocol), nil
}
func parseSSOutput(output string, protocol string) []ConnectionInfo {
var connections []ConnectionInfo
lines := strings.Split(output, "\n")
re := regexp.MustCompile(`(?P<Proto>\S+)\s+(?P<RecvQ>\S+)\s+(?P<SndQ>\S+)\s+(?P<LocalAddr>\S+)\s+(?P<PeerAddr>\S+)\s+(?P<Pid>\d+)/(?P<Path>.+)`)
for _, line := range lines {
if line == "" {
continue
}
matches := re.FindStringSubmatch(line)
if matches != nil {
pid, _ := strconv.Atoi(matches[6])
connections = append(connections, ConnectionInfo{
Protocol: protocol,
LocalAddr: matches[4],
RemoteAddr: matches[5],
PID: pid,
Path: matches[7],
})
}
}
return connections
}
跨平台方案
package main
import (
"fmt"
"log"
"github.com/shirou/gopsutil/net"
"github.com/shirou/gopsutil/process"
)
// ConnectionInfo 存储连接信息
type ConnectionInfo struct {
Protocol string
LocalAddr string
RemoteAddr string
PID int32
Path string
}
func main() {
conns, err := getConnections()
if err != nil {
log.Fatalf("Error getting connections: %v\n", err)
}
fmt.Println("Connections:")
for _, conn := range conns {
fmt.Printf("Protocol: %s, Local Address: %s, Remote Address: %s, PID: %d, Path: %s\n",
conn.Protocol, conn.LocalAddr, conn.RemoteAddr, conn.PID, conn.Path)
}
}
func getConnections() ([]ConnectionInfo, error) {
// 获取网络连接信息
connections, err := net.Connections("all")
if err != nil {
return nil, err
}
var connInfos []ConnectionInfo
for _, conn := range connections {
// 获取进程信息
pid := conn.Pid
var path string
if pid > 0 {
p, err := process.NewProcess(pid)
if err == nil {
path, _ = p.Exe() // 获取进程的路径
}
}
connInfos = append(connInfos, ConnectionInfo{
Protocol: conn.Type, // TCP/UDP
LocalAddr: conn.Laddr.String(),
RemoteAddr: conn.Raddr.String(),
PID: pid,
Path: path,
})
}
return connInfos, nil
}