赞
踩
- #ifdef _MSC_VER
- #define _WIN32_WINNT 0x0A00
- #endif
- #include <iostream>
- #include <vector>
- #include <boost/shared_ptr.hpp>
- #include <boost/asio.hpp>
- #include <boost/lexical_cast.hpp>
- #include <boost/bind.hpp>
- #include <boost/function.hpp>
- using namespace std;
-
- typedef boost::function<void(const boost::system::error_code&, const int&)> Callback;
- Callback funcRead_;
- Callback funcWrite_;
- boost::shared_ptr<boost::asio::io_service> io_service_;
- boost::shared_ptr<boost::asio::ip::udp::socket> socket_;
- vector<char> bufferRead_;
-
- void OnSendData(const boost::system::error_code& ErrorCode, const int& handle)
- {
- std::cout << "OnSendData" << std::endl;
-
- if (ErrorCode.value() != 0)
- {
- std::cout << " Error::Sending Data::" << ErrorCode.message() << std::endl;;
- }
- }
-
- void OnReceiveData(const boost::system::error_code& ErrorCode, const int& handle)
- {
- Sleep(100);
- std::cout << "OnReceiveData: " << ErrorCode.value() << " " << socket_->available() << std::endl;
-
- if (ErrorCode.value() == 0)
- {
- #if 1
- //socket_->available()会返回TCP/IP协议栈接收缓冲区内字节数,
- //也就是还未从TCP/IP协议栈接收缓冲区拷贝到asio缓冲区的字节数
- if (socket_->available() == 0)
- {
- //此时TCP/IP协议栈接收缓冲区的数据都已经拷贝到asio缓冲区,
- //可以进行业务数据处理
- for (int i = 0; i < bufferRead_.size(); i++)
- {
- std::cout << bufferRead_[i] << " ";
- }
- std::cout << std::endl;
-
- //将asio缓冲区置为null_buffers后,当再有UDP包到来时,
- //数据会存在TCP/IP协议栈接收缓冲区中,并会再次回调函数,
- //并且,socket_->available()会返回TCP/IP协议栈接收缓冲区内字节数
- socket_->async_receive(boost::asio::null_buffers(), funcRead_);
- }
- else
- {
- //当asio缓冲区置为null_buffers时,socket_->available()会返回TCP/IP协议栈接收缓冲区内字节数,
- //这里相当于提供了一个机会重新按照数据包尺寸按需设置asio缓冲区,
- //然后调用async_receive将TCP/IP协议栈接收缓冲区的数据拷贝到asio缓冲区
- //注意:此时async_receive为同步函数,
- //也就是TCP/IP协议栈接收缓冲区的数据会立即拷贝到asio缓冲区
- //然后会会再次回调函数,并且socket_->available()会返回0
- //如果设置了asio的缓冲区,但是大小小于UDP数据包的大小的话,那么多余的数据包将永远丢失
- bufferRead_.resize(socket_->available());
- socket_->async_receive(boost::asio::buffer(bufferRead_, bufferRead_.size()), funcRead_);
-
- //如果在初始化的时候把asio的缓冲区设置为null_buffers,
- //那么也可以在这里进行业务数据处理
- //如果在初始化的时候没有把asio的缓冲区设置为null_buffers,
- //那么这里收不到第一包数据
- for (int i = 0; i < bufferRead_.size(); i++)
- {
- std::cout << bufferRead_[i] << " ";
- }
- std::cout << std::endl;
- }
- #endif
-
- //下面这种做法适合数据包大小固定或者永远小于asio缓冲区的情况
- #if 0
- for (int i = 0; i < bufferRead_.size(); i++)
- {
- std::cout << bufferRead_[i] << " ";
- }
- std::cout << std::endl;
- socket_->async_receive(boost::asio::buffer(bufferRead_, bufferRead_.size()), funcRead_);
- #endif
- }
- }
-
- void StartReading(int n)
- {
- io_service_->run();
- }
-
- int main()
- {
- io_service_ = boost::shared_ptr<boost::asio::io_service>(new boost::asio::io_service);
- socket_ = boost::shared_ptr<boost::asio::ip::udp::socket>(new boost::asio::ip::udp::socket(*io_service_));
- socket_->open(boost::asio::ip::udp::v4());
-
- boost::asio::ip::udp::resolver resolver(*io_service_);
- boost::asio::ip::udp::resolver::query queryA("192.168.1.152", boost::lexical_cast<std::string> (48191));
- boost::asio::ip::udp::resolver::iterator udpEndPoint = resolver.resolve(queryA);
- boost::asio::ip::udp::resolver::query queryB("192.168.1.152", boost::lexical_cast<std::string> (48190));
- boost::asio::ip::udp::resolver::iterator udpLocalPoint = resolver.resolve(queryB);
-
- boost::system::error_code ec;
- boost::asio::ip::udp::socket::reuse_address ra(true);
- socket_->set_option(ra);
- socket_->set_option(boost::asio::socket_base::broadcast(true));
- socket_->bind(*udpLocalPoint);
- socket_->connect(*udpEndPoint, ec);
-
- funcWrite_ = boost::bind(OnSendData, boost::asio::placeholders::error, 0);
- funcRead_ = boost::bind(&OnReceiveData, boost::asio::placeholders::error, 0);
-
- //如果初始化的时候就将asio缓冲区设置为null_buffers,
- //那么业务数据处理在回调函数的socket_->available()两个分支都可以得到处理
- //因为每次会先调用socket_->available() > 0,然后调用socket_->available() == 0
- //如果初始化的时候没有将asio缓冲区设置为null_buffers,
- //那么第一包的业务数据处理只能在socket_->available() == 0的时候处理
- //但是这样作的话,可能会丢失数据,因为不知道缓冲区要设置为多大
- socket_->async_receive(boost::asio::null_buffers(), funcRead_);
- std::thread t(StartReading, NULL);
-
- std::vector<char> sendBuffer_(100);
- while (1)
- {
- std::cin >> &sendBuffer_[0];
- socket_->async_send_to(boost::asio::buffer(sendBuffer_, sendBuffer_.size()), *udpEndPoint, funcWrite_);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。