当前位置:   article > 正文

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

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 平台被微软禁用支援了。

头文件声明:

  1. class QoSS final
  2. {
  3. public:
  4. QoSS(int fd) noexcept;
  5. ~QoSS() noexcept;
  6. public:
  7. static std::shared_ptr<QoSS> New(int fd, const boost::asio::ip::address& host, int port) noexcept { return New(fd, host, port, false); }
  8. static std::shared_ptr<QoSS> New(int fd) noexcept { return New(fd, boost::asio::ip::address_v4::any(), 0, true); }
  9. private:
  10. static std::shared_ptr<QoSS> New(int fd, const boost::asio::ip::address& host, int port, bool noaddress) noexcept;
  11. private:
  12. int fd_ = -1;
  13. void* h_ = NULL;
  14. DWORD f_ = 0;
  15. };

源文件:

  1. QoSS::QoSS(int fd) noexcept
  2. : fd_(fd)
  3. , h_(NULL)
  4. , f_(NULL)
  5. {
  6. }
  7. QoSS::~QoSS() noexcept
  8. {
  9. if (NULL != h_)
  10. {
  11. if (f_ != 0)
  12. {
  13. QOSRemoveSocketFromFlow(h_, fd_, f_, 0);
  14. }
  15. QOSCloseHandle(h_);
  16. }
  17. }
  18. std::shared_ptr<QoSS> QoSS::New(int fd, const boost::asio::ip::address& host, int port, bool noaddress) noexcept
  19. {
  20. if (fd == INVALID_SOCKET)
  21. {
  22. return NULL;
  23. }
  24. std::shared_ptr<QoSS> qos = make_shared_object<QoSS>(fd);
  25. if (NULL == qos)
  26. {
  27. return NULL;
  28. }
  29. QOS_VERSION ver = { 1, 0 };
  30. if (!QOSCreateHandle(&ver, &qos->h_))
  31. {
  32. return NULL;
  33. }
  34. if (noaddress)
  35. {
  36. if (!QOSAddSocketToFlow(qos->h_, fd, NULL, QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &qos->f_))
  37. {
  38. return NULL;
  39. }
  40. }
  41. else
  42. {
  43. if (port <= IPEndPoint::MinPort || port > IPEndPoint::MaxPort)
  44. {
  45. return NULL;
  46. }
  47. if (!host.is_v4() && !host.is_v6())
  48. {
  49. return NULL;
  50. }
  51. if (IPEndPoint::IsInvalid(host))
  52. {
  53. return NULL;
  54. }
  55. if (host.is_v4())
  56. {
  57. sockaddr_in in{};
  58. in.sin_family = AF_INET;
  59. in.sin_port = htons(port);
  60. in.sin_addr.s_addr = htonl(host.to_v4().to_uint());
  61. if (!QOSAddSocketToFlow(qos->h_, fd, reinterpret_cast<sockaddr*>(&in), QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &qos->f_))
  62. {
  63. return NULL;
  64. }
  65. }
  66. else
  67. {
  68. sockaddr_in6 in6{};
  69. in6.sin6_family = AF_INET6;
  70. in6.sin6_port = htons(port);
  71. memcpy(&in6.sin6_addr, host.to_v6().to_bytes().data(), sizeof(in6.sin6_addr));
  72. if (!QOSAddSocketToFlow(qos->h_, fd, reinterpret_cast<sockaddr*>(&in6), QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &qos->f_))
  73. {
  74. return NULL;
  75. }
  76. }
  77. }
  78. // We shift the complete ToS value by 3 to get rid of the 3 bit ECN field
  79. DWORD dscp = 26;
  80. // Sets DSCP to the same as Linux
  81. // This will fail if we're not admin, but we ignore it
  82. if (!QOSSetFlow(qos->h_, qos->f_, QOSSetOutgoingDSCPValue, sizeof(DWORD), &dscp, 0, NULL))
  83. {
  84. return NULL;
  85. }
  86. return qos;
  87. }

参考文档:

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)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/391638
推荐阅读
相关标签
  

闽ICP备14008679号