微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

linux中tcp的真正最大段大小是多少?

如何解决linux中tcp的真正最大段大小是多少?

我能够从 getsockopt 获得 mss 值:

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。但是如果我尝试从客户端检查它:

client.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,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,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() 系统调用中看到真实的段大小,但是,如何确定商定的 {{1}应对应于 MSS 的对等体之间。在第一个 window 处,我得到了完整的缓冲区,(BUFSIZE == 8192),然后甚至没有一半,等等。

如何确定(都来自我的例子)

  1. MSS
  2. 节点之间的传播窗口(及其与 MSS 的关系)
  3. 每次发送操作之间段大小的变化程度(以及原因)

解决方法

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

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

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

至于 MSS,它表示 TCP 层的 Max Segment Size,因为我们使用了另一个名为 maximum transmission unit (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)。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?