0

我能够从以下位置获得 mss 值getsockopt

tcpmss.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>

int main()
{
    int sockfd, mss;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("sockfd");
        return 1;
    }

    socklen_t len = sizeof(mss);
    if (getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len) < 0)
    {
        perror("getsockopt");
        return 1;
    }

    printf("maximum segment size: %d\n", mss);
}

输出

maximum segment size: 536

其他消息来源说,默认 mss 是1460. 但是如果我尝试从客户端检查它:

客户端.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>

#define GET_CMD "GET %s HTTP/1.0\r\n\r\n"
#define SERV "80"
#define HOST "google.com"
#define HOMEPG "/"

//BUFSIZ = 8192, defined in <stdio.h>
int main()
{
    int sockfd, nbytes;
    struct addrinfo hints, *res;
    char buf[BUFSIZ];

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if (getaddrinfo(HOST, SERV, &hints, &res) != 0)
    {
        perror("getaddrinfo");
        return 1;
    }

    if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
    {
        perror("socket");
        return 1;
    }

    if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0)
    {
        perror("connect");
        return 1;
    }

    nbytes = snprintf(buf, 256, GET_CMD, HOMEPG);
    if (write(sockfd, buf, nbytes) < 0)
    {
        perror("write");
        return 1;
    }

    while ((nbytes = read(sockfd, buf, BUFSIZ)) > 0)
    {
        printf("read %d bytes of home page of %s\n", nbytes, HOST);
    }
    if (nbytes == 0)
    {
        printf("got EOF from google.com");
    }
}

输出

read 8192 bytes of home page of google.com
read 3888 bytes of home page of google.com
read 7248 bytes of home page of google.com
read 4832 bytes of home page of google.com
read 6040 bytes of home page of google.com
read 6040 bytes of home page of google.com
read 6040 bytes of home page of google.com
read 4832 bytes of home page of google.com
read 2229 bytes of home page of google.com
got EOF from google.com

这些值都不是真的。所以我对最大段大小有点困惑。我知道该read()块并将更多段提取tcp到内核接收缓冲区中,因此我无法从read()系统调用中看到真实的段大小,但是,如何确定window应对应于 MSS 的对等方之间的约定。在第一个read(),我得到了完整的缓冲区,(BUFSIZE == 8192),然后甚至没有一半,等等。

如何确定(全部来自我的示例)

  1. MSS
  2. 对等点之间的传播窗口(及其与 MSS 的关系)
  3. 每个发送操作之间有多少段大小变化(以及为什么)
4

1 回答 1

1

这是一个相对较大的问题,因为它包含很多东西。

在深入回答之前,我认为最重要的是要了解网络是一条复杂而漫长的道路。我们将路径划分为若干层,每一层可能有不同的协议,这使事情变得更加复杂。所以当你发现一个关于 TCP 的有趣的事情时,有时我们还需要查看下层/上层才能看到整个路径。

首先,我们总是使用 tcpdump 和 wireshark 来分析网络以获取更多细节,这可以帮助您深入了解网络。

至于MSS,它表示 TCP 层的 Max Segment Size,因为我们使用了另一个限制,称为最大传输单元 (MTU),它是可以在单个网络层中通信的最大协议数据单元 (PDU) 的大小事务,MSS 总是需要减少一些头部的长度。

对于 TCP 协议的窗口,这里有很多不同的因素我们必须考虑。我们使用窗口是因为 TCP 需要 ACK 来实现可靠传输,发送/接收窗口可以检查这一点(也因为一些其他原因而开发)。但是随着网络流的炸裂,TCP增加了拥塞控制,所以窗口也必须由拥塞窗口来编辑。MSS/MTU 被用作计算默认值的一个因素,但在此之后,许多协议/算法协同工作以使窗口发生变化,以确保 TCP 连接的可靠和高效工作。

对于大数据包,TCP可以在接收时将它们拆分,然后将它们组合在一起。更重要的是,硬件也可以做到。这里有很多技术,如TSO(TCP Segmentation Offload)、UFO(UDP Fragmentation Offload)、GSO(Generic Segmentation Offload)、LRO(Large Receive Offload)和GRO(Generic Receive Offload)。

所以你看,这真的很有趣也很复杂。

于 2021-02-02T09:46:56.460 回答