赞
踩
本体提供的函数实现,只能对于TCP生效,UDP没法生效,看文档没搞明白,有了解UDP怎么设置DSCP的童鞋,可以在评论区给予答复。
用法是这样的,每个TCP在建立链接后,立即创建这个QOSS的实例,当然也可以在链接前,但在连接前有一定限制就是说,你必须在连接前把IP+PORT地址传进去,链接建立后在创建QOS就不需要传入IP+PORT地址。
同时,在关联的TCP链接关闭时需要销毁这个,否则就会产生QOS2内核句柄资源泄漏。
DSCP值26,就等于 IP_TOS: 0x68,即FLASH,[IPTOS_LOWDELAY] 宏的效果【MACOS/LINUX】上,Windows 平台被微软禁用支援了。
头文件声明:
- 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;
- };

源文件:
- 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)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。