TCP在发送超过最大分段大小(MSS)的大数据包时是如何组合数据的?

huangapple go评论92阅读模式
英文:

How does TCP combine data when sending a big data packet which is over MSS?

问题

这是一个tcpdump演示。

  • seq 1 - 52001是大数据,超过我的回环MSS(16384)。
  • seq 52001 - 52013是小数据。

TCP如何知道seq 1 - 52001是一个组合的数据块,seq 52001 - 52013是另一个组合的数据块?

以下是我的客户端代码:

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:30000")
    if err != nil {
        fmt.Println("拨号失败,错误", err)
        return
    }
    defer conn.Close()
    msg := ""
    for i := 0; i < 2000; i++ {
        msg += `你好,你好。你好吗?`

    }
    conn.Write([]byte(msg))

    conn.Write([]byte("演示内容"))
}
英文:

Here is a tcpdump demo.

  • seq 1 - 52001 is big data, over my loopback MSS (16384).
  • seq 52001 - 52013 is small data.

How does TCP know seq 1 - 52001 is a combined data block and seq 52001 - 52013 is another combined data block?

23:10:00.773752 IP localhost.56006 &gt; localhost.30000: Flags [S], seq 3081455670, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 807676974 ecr 0,sackOK,eol], length 0
23:10:00.774059 IP localhost.30000 &gt; localhost.56006: Flags [S.], seq 1040822423, ack 3081455671, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 3518795094 ecr 807676974,sackOK,eol], length 0
23:10:00.774101 IP localhost.56006 &gt; localhost.30000: Flags [.], ack 1, win 6379, options [nop,nop,TS val 807676974 ecr 3518795094], length 0
23:10:00.774125 IP localhost.30000 &gt; localhost.56006: Flags [.], ack 1, win 6379, options [nop,nop,TS val 3518795094 ecr 807676974], length 0
23:10:00.783835 IP localhost.56006 &gt; localhost.30000: Flags [.], seq 1:16333, ack 1, win 6379, options [nop,nop,TS val 807676984 ecr 3518795094], length 16332
23:10:00.783840 IP localhost.56006 &gt; localhost.30000: Flags [.], seq 16333:32665, ack 1, win 6379, options [nop,nop,TS val 807676984 ecr 3518795094], length 16332
23:10:00.783843 IP localhost.56006 &gt; localhost.30000: Flags [.], seq 32665:48997, ack 1, win 6379, options [nop,nop,TS val 807676984 ecr 3518795094], length 16332
23:10:00.783847 IP localhost.56006 &gt; localhost.30000: Flags [P.], seq 48997:52001, ack 1, win 6379, options [nop,nop,TS val 807676984 ecr 3518795094], length 3004
23:10:00.783861 IP localhost.56006 &gt; localhost.30000: Flags [P.], seq 52001:52013, ack 1, win 6379, options [nop,nop,TS val 807676984 ecr 3518795094], length 12
23:10:00.783874 IP localhost.56006 &gt; localhost.30000: Flags [F.], seq 52013, ack 1, win 6379, options [nop,nop,TS val 807676984 ecr 3518795094], length 0
23:10:00.784068 IP localhost.30000 &gt; localhost.56006: Flags [.], ack 16333, win 6124, options [nop,nop,TS val 3518795104 ecr 807676984], length 0
23:10:00.784106 IP localhost.30000 &gt; localhost.56006: Flags [.], ack 32665, win 5869, options [nop,nop,TS val 3518795104 ecr 807676984], length 0
23:10:00.784110 IP localhost.30000 &gt; localhost.56006: Flags [.], ack 48997, win 5614, options [nop,nop,TS val 3518795104 ecr 807676984], length 0
23:10:00.784114 IP localhost.30000 &gt; localhost.56006: Flags [.], ack 52001, win 5567, options [nop,nop,TS val 3518795104 ecr 807676984], length 0
23:10:00.784121 IP localhost.30000 &gt; localhost.56006: Flags [.], ack 52013, win 5567, options [nop,nop,TS val 3518795104 ecr 807676984], length 0
23:10:00.784139 IP localhost.30000 &gt; localhost.56006: Flags [.], ack 52014, win 5567, options [nop,nop,TS val 3518795104 ecr 807676984], length 0
23:10:00.798479 IP localhost.30000 &gt; localhost.56006: Flags [F.], seq 1, ack 52014, win 5567, options [nop,nop,TS val 3518795119 ecr 807676984], length 0
23:10:00.798571 IP localhost.56006 &gt; localhost.30000: Flags [.], ack 2, win 6379, options [nop,nop,TS val 807676999 ecr 3518795119], length 0

Here is my client code:

func main() {
	conn, err := net.Dial(&quot;tcp&quot;, &quot;127.0.0.1:30000&quot;)
	if err != nil {
		fmt.Println(&quot;dial failed, err&quot;, err)
		return
	}
	defer conn.Close()
	msg := &quot;&quot;
	for i := 0; i &lt; 2000; i++ {
		msg += `Hello, Hello. How are you?`

	}
	conn.Write([]byte(msg))

	conn.Write([]byte(&quot;demo content&quot;))
}

答案1

得分: 2

TCP如何知道序列1 - 52001是一个组合数据块,序列52001 - 52013是另一个组合数据块呢?

它并不知道。从TCP的角度来看,这只是一个没有任何内部结构的字节流。任何结构(比如一个“消息”)都需要由应用程序协议添加。

换句话说,你不能期望发送端的单次写入/发送会在接收端产生单次读取/接收。

英文:

> How does TCP know seq 1 - 52001 is a combined data block and seq 52001 - 52013 is another combined data block?

It doesn't. From the perspective of TCP this is only a byte stream without any internal structure. Any structure (like a "message") needs to be added by the application protocol.

Or in other words: you cannot expect that a single write/send in the sender will result in a single read/recv in the recpient.

huangapple
  • 本文由 发表于 2023年7月23日 23:19:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76749002.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定