

新闻资讯
技术学院在 go 的 tcp 服务端程序中,调用 `conn.remoteaddr()` 即可准确获取客户端的 ip 地址和源端口号,该方法返回的地址与操作系统底层网络状态(如 `netstat`)完全一致,无需额外解析或调试。
在基于 Go 编写的 TCP 服务器中,当通过 listener.Accept() 接收一个新连接后,得到的 net.Conn 接口提供了两个关键地址方法:LocalAddr() 和 RemoteAddr()。其中:
⚠️ 注意:部分开发者误以为 RemoteAddr() 返回的端口不正确,通常是由于混淆了「客户端绑定端口」与「客户端连接时由内核分配的临时源端口」。TCP 客户端在调用 net.Dial() 时若未显式 Bind(),系统会自动分配一个可用的 ephemeral port(通常在 32768–65535 范围),而 conn.RemoteA
ddr() 正是返回这个真实通信源端口——它与 netstat -an 或 lsof -i 输出完全一致,绝对可靠。
以下是一个最小可验证示例:
package main
import (
"fmt"
"net"
"time"
)
func main() {
ln, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
defer ln.Close()
fmt.Println("Server listening on :8080...")
for {
conn, err := ln.Accept()
if err != nil {
fmt.Printf("Accept error: %v\n", err)
continue
}
// ✅ 正确获取客户端地址:IP + 实际源端口
clientAddr := conn.RemoteAddr()
fmt.Printf("New connection from: %s\n", clientAddr)
// 可选:提取 IP 和端口进行进一步处理
if addr, ok := clientAddr.(*net.TCPAddr); ok {
fmt.Printf("Client IP: %s, Port: %d\n", addr.IP, addr.Port)
}
// 简单响应后关闭(仅用于演示)
conn.Write([]byte("Hello from server!\n"))
time.Sleep(100 * time.Millisecond)
conn.Close()
}
}运行此服务端后,使用任意客户端(如 nc 127.0.0.1 8080 或自定义 Go 客户端)连接,控制台将输出类似:
New connection from: 127.0.0.1:54321 Client IP: 127.0.0.1, Port: 54321
同时在终端执行 netstat -an | grep :8080,你将看到匹配的 ESTABLISHED 行:
tcp4 0 0 127.0.0.1.8080 127.0.0.1.54321 ESTABLISHED
✅ 总结:
这是 Go 标准库对 TCP 协议栈的规范封装,简洁、高效且跨平台可靠。