当前位置:   article > 正文

boost::asio udp异步收发数据_boost asio udp

boost asio udp
  1. #ifdef _MSC_VER
  2. #define _WIN32_WINNT 0x0A00
  3. #endif
  4. #include <iostream>
  5. #include <vector>
  6. #include <boost/shared_ptr.hpp>
  7. #include <boost/asio.hpp>
  8. #include <boost/lexical_cast.hpp>
  9. #include <boost/bind.hpp>
  10. #include <boost/function.hpp>
  11. using namespace std;
  12. typedef boost::function<void(const boost::system::error_code&, const int&)> Callback;
  13. Callback funcRead_;
  14. Callback funcWrite_;
  15. boost::shared_ptr<boost::asio::io_service> io_service_;
  16. boost::shared_ptr<boost::asio::ip::udp::socket> socket_;
  17. vector<char> bufferRead_;
  18. void OnSendData(const boost::system::error_code& ErrorCode, const int& handle)
  19. {
  20. std::cout << "OnSendData" << std::endl;
  21. if (ErrorCode.value() != 0)
  22. {
  23. std::cout << " Error::Sending Data::" << ErrorCode.message() << std::endl;;
  24. }
  25. }
  26. void OnReceiveData(const boost::system::error_code& ErrorCode, const int& handle)
  27. {
  28. Sleep(100);
  29. std::cout << "OnReceiveData: " << ErrorCode.value() << " " << socket_->available() << std::endl;
  30. if (ErrorCode.value() == 0)
  31. {
  32. #if 1
  33. //socket_->available()会返回TCP/IP协议栈接收缓冲区内字节数,
  34. //也就是还未从TCP/IP协议栈接收缓冲区拷贝到asio缓冲区的字节数
  35. if (socket_->available() == 0)
  36. {
  37. //此时TCP/IP协议栈接收缓冲区的数据都已经拷贝到asio缓冲区,
  38. //可以进行业务数据处理
  39. for (int i = 0; i < bufferRead_.size(); i++)
  40. {
  41. std::cout << bufferRead_[i] << " ";
  42. }
  43. std::cout << std::endl;
  44. //将asio缓冲区置为null_buffers后,当再有UDP包到来时,
  45. //数据会存在TCP/IP协议栈接收缓冲区中,并会再次回调函数,
  46. //并且,socket_->available()会返回TCP/IP协议栈接收缓冲区内字节数
  47. socket_->async_receive(boost::asio::null_buffers(), funcRead_);
  48. }
  49. else
  50. {
  51. //当asio缓冲区置为null_buffers时,socket_->available()会返回TCP/IP协议栈接收缓冲区内字节数,
  52. //这里相当于提供了一个机会重新按照数据包尺寸按需设置asio缓冲区,
  53. //然后调用async_receive将TCP/IP协议栈接收缓冲区的数据拷贝到asio缓冲区
  54. //注意:此时async_receive为同步函数,
  55. //也就是TCP/IP协议栈接收缓冲区的数据会立即拷贝到asio缓冲区
  56. //然后会会再次回调函数,并且socket_->available()会返回0
  57. //如果设置了asio的缓冲区,但是大小小于UDP数据包的大小的话,那么多余的数据包将永远丢失
  58. bufferRead_.resize(socket_->available());
  59. socket_->async_receive(boost::asio::buffer(bufferRead_, bufferRead_.size()), funcRead_);
  60. //如果在初始化的时候把asio的缓冲区设置为null_buffers,
  61. //那么也可以在这里进行业务数据处理
  62. //如果在初始化的时候没有把asio的缓冲区设置为null_buffers,
  63. //那么这里收不到第一包数据
  64. for (int i = 0; i < bufferRead_.size(); i++)
  65. {
  66. std::cout << bufferRead_[i] << " ";
  67. }
  68. std::cout << std::endl;
  69. }
  70. #endif
  71. //下面这种做法适合数据包大小固定或者永远小于asio缓冲区的情况
  72. #if 0
  73. for (int i = 0; i < bufferRead_.size(); i++)
  74. {
  75. std::cout << bufferRead_[i] << " ";
  76. }
  77. std::cout << std::endl;
  78. socket_->async_receive(boost::asio::buffer(bufferRead_, bufferRead_.size()), funcRead_);
  79. #endif
  80. }
  81. }
  82. void StartReading(int n)
  83. {
  84. io_service_->run();
  85. }
  86. int main()
  87. {
  88. io_service_ = boost::shared_ptr<boost::asio::io_service>(new boost::asio::io_service);
  89. socket_ = boost::shared_ptr<boost::asio::ip::udp::socket>(new boost::asio::ip::udp::socket(*io_service_));
  90. socket_->open(boost::asio::ip::udp::v4());
  91. boost::asio::ip::udp::resolver resolver(*io_service_);
  92. boost::asio::ip::udp::resolver::query queryA("192.168.1.152", boost::lexical_cast<std::string> (48191));
  93. boost::asio::ip::udp::resolver::iterator udpEndPoint = resolver.resolve(queryA);
  94. boost::asio::ip::udp::resolver::query queryB("192.168.1.152", boost::lexical_cast<std::string> (48190));
  95. boost::asio::ip::udp::resolver::iterator udpLocalPoint = resolver.resolve(queryB);
  96. boost::system::error_code ec;
  97. boost::asio::ip::udp::socket::reuse_address ra(true);
  98. socket_->set_option(ra);
  99. socket_->set_option(boost::asio::socket_base::broadcast(true));
  100. socket_->bind(*udpLocalPoint);
  101. socket_->connect(*udpEndPoint, ec);
  102. funcWrite_ = boost::bind(OnSendData, boost::asio::placeholders::error, 0);
  103. funcRead_ = boost::bind(&OnReceiveData, boost::asio::placeholders::error, 0);
  104. //如果初始化的时候就将asio缓冲区设置为null_buffers,
  105. //那么业务数据处理在回调函数的socket_->available()两个分支都可以得到处理
  106. //因为每次会先调用socket_->available() > 0,然后调用socket_->available() == 0
  107. //如果初始化的时候没有将asio缓冲区设置为null_buffers,
  108. //那么第一包的业务数据处理只能在socket_->available() == 0的时候处理
  109. //但是这样作的话,可能会丢失数据,因为不知道缓冲区要设置为多大
  110. socket_->async_receive(boost::asio::null_buffers(), funcRead_);
  111. std::thread t(StartReading, NULL);
  112. std::vector<char> sendBuffer_(100);
  113. while (1)
  114. {
  115. std::cin >> &sendBuffer_[0];
  116. socket_->async_send_to(boost::asio::buffer(sendBuffer_, sendBuffer_.size()), *udpEndPoint, funcWrite_);
  117. }
  118. }

 

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

闽ICP备14008679号