VC++ Windows 平台通过QOS2库函数设置Socket DSCP(IP_TOS)参数选项

本体提供的函数实现,只能对于TCP生效,UDP没法生效,看文档没搞明白,有了解UDP怎么设置DSCP的童鞋,可以在评论区给予答复。

用法是这样的,每个TCP在建立链接后,立即创建这个QOSS的实例,当然也可以在链接前,但在连接前有一定限制就是说,你必须在连接前把IP+PORT地址传进去,链接建立后在创建QOS就不需要传入IP+PORT地址。

同时,在关联的TCP链接关闭时需要销毁这个,否则就会产生QOS2内核句柄资源泄漏。

DSCP值26,就等于 IP_TOS: 0x68,即FLASH,[IPTOS_LOWDELAY] 宏的效果【MACOS/LINUX】上,Windows 平台被微软禁用支援了。

头文件声明:

cpp 复制代码
        class QoSS final
        {
        public:
            QoSS(int fd) noexcept;
            ~QoSS() noexcept;

        public:
            static std::shared_ptr<QoSS>            New(int fd, const boost::asio::ip::address& host, int port) noexcept { return New(fd, host, port, false); }
            static std::shared_ptr<QoSS>            New(int fd) noexcept { return New(fd, boost::asio::ip::address_v4::any(), 0, true); }

        private:
            static std::shared_ptr<QoSS>            New(int fd, const boost::asio::ip::address& host, int port, bool noaddress) noexcept;

        private:
            int                                     fd_ = -1;
            void*                                   h_  = NULL;
            DWORD                                   f_  = 0;
        };

源文件:

cpp 复制代码
        QoSS::QoSS(int fd) noexcept
            : fd_(fd)
            , h_(NULL)
            , f_(NULL)
        {

        }

        QoSS::~QoSS() noexcept
        {
            if (NULL != h_)
            {
                if (f_ != 0)
                {
                    QOSRemoveSocketFromFlow(h_, fd_, f_, 0);
                }

                QOSCloseHandle(h_);
            }
        }

        std::shared_ptr<QoSS> QoSS::New(int fd, const boost::asio::ip::address& host, int port, bool noaddress) noexcept
        {
            if (fd == INVALID_SOCKET)
            {
                return NULL;
            }

            std::shared_ptr<QoSS> qos = make_shared_object<QoSS>(fd);
            if (NULL == qos)
            {
                return NULL;
            }

            QOS_VERSION ver = { 1, 0 };
            if (!QOSCreateHandle(&ver, &qos->h_))
            {
                return NULL;
            }

            if (noaddress)
            {
                if (!QOSAddSocketToFlow(qos->h_, fd, NULL, QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &qos->f_))
                {
                    return NULL;
                }
            }
            else
            {
                if (port <= IPEndPoint::MinPort || port > IPEndPoint::MaxPort)
                {
                    return NULL;
                }

                if (!host.is_v4() && !host.is_v6())
                {
                    return NULL;
                }

                if (IPEndPoint::IsInvalid(host))
                {
                    return NULL;
                }

                if (host.is_v4())
                {
                    sockaddr_in in{};
                    in.sin_family = AF_INET;
                    in.sin_port = htons(port);
                    in.sin_addr.s_addr = htonl(host.to_v4().to_uint());

                    if (!QOSAddSocketToFlow(qos->h_, fd, reinterpret_cast<sockaddr*>(&in), QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &qos->f_))
                    {
                        return NULL;
                    }
                }
                else
                {
                    sockaddr_in6 in6{};
                    in6.sin6_family = AF_INET6;
                    in6.sin6_port = htons(port);
                    memcpy(&in6.sin6_addr, host.to_v6().to_bytes().data(), sizeof(in6.sin6_addr));

                    if (!QOSAddSocketToFlow(qos->h_, fd, reinterpret_cast<sockaddr*>(&in6), QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &qos->f_))
                    {
                        return NULL;
                    }
                }
            }

            // We shift the complete ToS value by 3 to get rid of the 3 bit ECN field
            DWORD dscp = 26;

            // Sets DSCP to the same as Linux
            // This will fail if we're not admin, but we ignore it
            if (!QOSSetFlow(qos->h_, qos->f_, QOSSetOutgoingDSCPValue, sizeof(DWORD), &dscp, 0, NULL))
            {
                return NULL;
            }

            return qos;
        }

参考文档:

https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options#windows-support-for-ip_proto-options

https://learn.microsoft.com/en-us/windows-server/networking/technologies/qos/qos-policy-manage#advanced-qos-settings-dscp-marking-override

https://learn.microsoft.com/en-us/windows-server/networking/technologies/qos/qos-policy-manage#advanced-qos-settings-dscp-marking-override

https://learn.microsoft.com/en-us/previous-versions/windows/desktop/dd874008(v=vs.85)

相关推荐
LaoZhangGong12312 分钟前
W5500使用ioLibrary库创建TCP客户端
网络·经验分享·stm32·网络协议·tcp/ip
q5673152325 分钟前
图片爬虫通过模板及使用说明
开发语言·爬虫·tcp/ip·golang
麟城Lincoln1 小时前
【Linux笔记】nfs网络文件系统与autofs(nfsdata、autofs、autofs.conf、auto.master)
linux·网络·笔记·nfs·autofs
Funny-Boy1 小时前
Reactor (epoll实现基础)
服务器·网络·c++
tmacfrank2 小时前
Java 原生网络编程(BIO | NIO | Reactor 模式)
java·开发语言·网络
天天爱吃肉82182 小时前
车载以太网驱动智能化:域控架构设计与开发实践
java·运维·网络协议·微服务
IP管家3 小时前
企业级IP代理解决方案:负载均衡与API接口集成实践
服务器·网络·数据库·网络协议·tcp/ip·容器·负载均衡
RockLiu@8053 小时前
自适应稀疏核卷积网络:一种高效灵活的图像处理方案
网络·图像处理·人工智能
{⌐■_■}4 小时前
【gRPC】HTTP/2协议,HTTP/1.x中线头阻塞问题由来,及HTTP/2中的解决方案,RPC、Protobuf、HTTP/2 的关系及核心知识点汇总
网络·网络协议·计算机网络·http·rpc·golang
Clownseven4 小时前
[IP地址科普] 服务器公网IP、私网IP、弹性IP是什么?区别与应用场景详解
服务器·网络协议·tcp/ip