Golang原始套接字丢失数据包?

时间:2018-06-22 20:06:41

标签: sockets go networking

我正在用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服务器成功下载了整个正文。

1 个答案:

答案 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中接收的数据包已经被处理,即重新排序。或者至少我希望,因为没有太多的文档。)

此外,调整延迟后,数据包丢失也会改变。