C/C++ Socket 获取或设置 TCP MSS 大小

61 篇文章 3 订阅

通过 Socket 系统接口,链接到一个TCP服务器,那么在链接成功之后会被配置一个从本地端到目的端最佳的TCP_MSS大小。

我们通过这个特点,即可轻松的实现,链路MTU大小发现功能,在不依赖ROOT管理员权限的情况下,推算出一个较为OK的MTU大小。

一般来说,TCP在服务器SYN|ACK的时候,指定的TCP选项设置的最大分段大小,通常是需要-12字节的,这是因为在PUSH/ACK分段的时候头部有扩展12字节的TCP选项,两个NOP填充,一个TIMESPAN时间戳。

所以:

 当如上图,TCP选项协商设置最大分段大小为;1332,那么意味着TCP_MSS为1320,扣除TCP PUSH/在协议头上额外设定的12字节,一个TCP选项占四个字节,三个则12字节。

 

所以:

我们只要需要通过 socket 接口,获取 TCP_MAXSEG 的值,加12,那么就是TCP的大小,IPV4头20字节,那么意味着;

MTU=1320+12+20=1352,则:从本机到目的主机最佳MTU大小为1352,理论更大会导致传输效率的降低,因为这意味着沿途某一个路由需要进行分片传输。

注意:

TCP是通过 “Path MTU Discovery(PMTUD)” 路径MTU发现机制来探测MTU大小的,但是这个在非TCP模式下不可用。

其原理大致为:

1、 发送端发送一个较大尺寸的数据包,并将 "Don't Fragment"(DF)标志位置为1,这样数据包就不会在传输过程中被分片。

2、如果数据包超出了某个路由器的MTU,该路由器将会丢弃数据包,并向发送端发送一个 "ICMP Fragmentation Needed" 消息,其中包含其MTU值。

3、发送端收到 "ICMP Fragmentation Needed" 消息后,会调整其传输数据包的大小,使其不超过最小的发现的MTU值。然后继续发送新的数据包进行测试,直到找到两个节点之间的最佳MTU值。

PMTUD机制是操作系统内核协议栈已经实现的功能,当我们调用 connect 函数的时候,内核那边就会做这样的行为,当然如果已有缓存就不会触发PMTUD机制,这个可以抓包工具来分析。

函数: 

 GetTcpMss 获取TCP_MSS大小 

SetTcpMss 设置TCP_MSS大小

        /* TCP MSS values – what’s changed?
         * https://blog.apnic.net/2019/07/31/tcp-mss-values-whats-changed/ 
         */
        int Socket::GetTcpMss(int fd) noexcept {
            if (fd == -1) {
                return -1;
            }

            int mss = 0;
            socklen_t mss_len = sizeof(mss);

            if (::getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (char*)&mss, &mss_len) < 0) {
                return -1;
            }

            return mss;
        }

        bool Socket::SetTcpMss(int fd, int mss) noexcept {
            static constexpr int TCP_MIN_MSS = 536;
            static constexpr int TCP_MAX_MSS = 1460;

            if (fd == -1) {
                return false;
            }

            if (mss < TCP_MIN_MSS) {
                mss = TCP_MIN_MSS;
            }
            elif(mss > TCP_MAX_MSS) {
                mss = TCP_MAX_MSS;
            }

            int err = ::setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (char*)&mss, sizeof(mss));
            return err == 0;
        }

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值