我正在用Golang写一个简单的程序来使用原始套接字捕获TCP / IP数据包:
package main
import (
"fmt"
"log"
"net"
)
func main() {
netaddr, err := net.ResolveIPAddr("ip", "127.0.0.1")
if err != nil {
log.Fatal(err)
}
conn, err := net.ListenIP("ip:tcp", netaddr)
if err != nil {
log.Fatal(err)
}
packet := make([]byte, 64*1024)
numPackets := 0
totalLen := 0
for {
packetLen, _, err := conn.ReadFrom(packet)
if err != nil {
log.Fatal(err)
}
dataOffsetWords := (packet[12] & 0xF0) >> 4
dataOffset := 4 * dataOffsetWords
payload := packet[dataOffset:packetLen]
numPackets += 1
totalLen += len(payload)
fmt.Println("Num packets:", numPackets, ", Total len:", totalLen)
}
}
当我将程序接收到的数据包数量及其包含的数据总量与Wiresharks看到的数据包数量以及传输的总数据进行比较时,我知道我丢失了所有数据包和数据的15%至30%每次运行。
为什么?
我唯一想到的是应用程序的接收速度不够快,但这很奇怪。 (我正在localhost上进行通信,并发送约17 MB的数据。)但是,Goreplay使用了类似的东西并且可以工作。
我所收到的流量是通过curl
进入本地运行的Python服务器(http.server
)并在请求正文中发送大文件而创建的。 Python服务器成功下载了整个正文。
答案 0 :(得分:0)
我最初的猜想是对的:通过修改接收的Python服务器,使其不立即读取所有传入数据:
post_body = self.rfile.read(content_len)
但是在迭代之间有10毫秒的延迟的循环中:
while (total_len < content_len):
post_body = self.rfile.read(min(16536, content_len - total_len))
total_len += len(post_body)
time.sleep(1 / 100.)
我在Golang中接收了所有数据,并且处理的数据包的数量大致相同(我假设只有很少的匹配,因为在Golang中接收的数据包已经被处理,即重新排序。或者至少我希望,因为没有太多的文档。)
此外,调整延迟后,数据包丢失也会改变。