13.8 底层网络编程
虽然 http.Transport 结构允许您修改网络连接的底层参数,但您可以编写允许您读取网络包原始数据的 Go 代码。这有两个棘手的问题:
网络包采用二进制格式,这要求您查找特定类型的网络数据包,而不仅仅是任何类型的网络数据包。
为了发送一个网络数据包,您必须自己构建。
接下来要展示的是 lowLevel.go,并把它分为三个部分。注意 lowLevel.go 捕获 ICMP 数据包,使用 IPv4 协议并打印包的内容。另外,由于安全原因操作原始网络数据需求 root 权限。
lowLevel.go 的第一段如下:
package main
import(
"fmt"
"net"
)lowLevel.go 的第二段代码如下:
func main() {
netaddr, err := net.ResolveIPAddr("ip4", "127.0.0.1")
if err != nil {
fmt.Println(err)
return
}
conn, err := net.ListenIP("ip4:icmp", netaddr)
if err != nil {
fmt.Println(err)
return
}ICMP 协协议被定义在 net.ListenIP() 函数的第一个参数的第二部分。此外,ip4 部分告诉程序只捕获 IPv4 流量。
lowLevel.go 的其余 Go 代码如下:
上面这段代码告诉 lowLevel.go 只读取一个网络包,因为没有 for 循环。
ICMP 协议由 ping(1) 和 traceroute(1) 命令使用,所以为了产生 ICMP 流量,可以使用它们中的任何一个。当 lowLevel.go 已经运行后,在所有的 Unix 机器上使用如下命令就会产生 ICMP 网络流量。
在 macOS High Sierra 机器上用 root 权限执行 lowLevel.go 将产生如下输出:
第一个输出的例子是 ping(1) 命令产生的,第二个是 traceroute(1) 命令产生的。
在 Debian Linux 机器上运行 lowLevel.go 将产生如下输出:
uname(1) 命令打印出 Linux 系统的有用信息。注意,在当前的 Linux 机器上,您应该在执行 ping(1) 命令时使用 -4 标志来告诉它使用 IPv4 协议。
Last updated
Was this helpful?