Golang接收ICMP数据包吞吐量低的问题
Golang接收ICMP数据包吞吐量低的问题 我正在尝试使用Go语言并行ping尽可能多的地址。
目前我使用一个Golang程序发送ICMP数据包,另一个程序接收ICMP数据包。发送数据包没有问题,但"接收器"在从套接字读取时会不断"暂停"。
fd, _ := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
f := os.NewFile(uintptr(fd), fmt.Sprintf("fd %d", fd))
i := 0
for {
buf := make([]byte, 1024)
numRead, err := f.Read(buf)
if err != nil {
fmt.Println(err)
}
_ = numRead
//fmt.Printf("% X\n", buf[:numRead])
fmt.Println(i)
i++
}
这段代码大约能读取250个数据包/秒,之后就会忽略大部分数据包。
谢谢
更多关于Golang接收ICMP数据包吞吐量低的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang接收ICMP数据包吞吐量低的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
问题可能出现在使用os.File包装原始套接字进行读取的方式上。原始套接字需要更底层的系统调用处理,而os.File.Read可能引入了不必要的缓冲或系统调用开销。建议直接使用syscall.Read或切换到golang.org/x/net/ipv4包进行更高效的ICMP数据包处理。
以下是改进后的代码示例,使用syscall.Read直接操作文件描述符:
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
if err != nil {
panic(err)
}
defer syscall.Close(fd)
i := 0
for {
buf := make([]byte, 1024)
numRead, err := syscall.Read(fd, buf)
if err != nil {
fmt.Println(err)
continue
}
_ = numRead
//fmt.Printf("% X\n", buf[:numRead])
fmt.Println(i)
i++
}
或者使用golang.org/x/net/ipv4包:
import "golang.org/x/net/ipv4"
conn, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
panic(err)
}
defer conn.Close()
p := ipv4.NewPacketConn(conn)
p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true)
i := 0
buf := make([]byte, 1024)
for {
n, cm, _, err := p.ReadFrom(buf)
if err != nil {
fmt.Println(err)
continue
}
_ = n
_ = cm
//fmt.Printf("% X\n", buf[:n])
fmt.Println(i)
i++
}
这些方法应该能显著提高ICMP数据包的接收吞吐量。

