boost库在工作(39)网络UDP异步服务端之九

 

前面创建的UDP服务器和客户端,都是同步的方式,也就是说当接收数据时,不能参与别的事情执行的。如果在一个只有界面线程的程序里,又不想创建多线程,导致复杂程度的增加,在这种情况之下,我们还有一个方案可以选择,就是创建一个异步的UDP服务器或客户端,这样既有单线程的简单性,也可以让客户随便操作界面的快速响应的特性。在boost库里使用io_service对象来实现异步是轻而易举的事情,因为封装的接口简单、明了。具体的代码如下:

[cpp] view plaincopy
 
  1. // boost_028.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <ctime>  
  6.   
  7. #include <boost/asio/ip/tcp.hpp>  
  8. #include <boost/asio.hpp>  
  9. #include <boost/bind.hpp>  
  10. #include <boost/enable_shared_from_this.hpp>  
  11. #include <boost/shared_ptr.hpp>  
  12. #include <boost/array.hpp>  
  13.   
  14. #include <iostream>  
  15. #include <string>  
  16.   
  17. //使用UDP命名空间  
  18. using boost::asio::ip::udp;  
  19.   
  20. //把当前时间转换为字符串。  
  21. std::string make_daytime_string()  
  22. {  
  23.     using namespace std; //为了使用time_t, time 和 ctime;  
  24.     time_t now = time(0);  
  25.     return ctime(&now);  
  26. }  
  27.   
  28. //  
  29. //创建一个异步UDP的时间服务器。  
  30. //软件开发人员: 蔡军生  2013-08-25   
  31. //QQ: 9073204  
  32. //  
  33. class UdpTimeServer  
  34. {  
  35. public:  
  36.     //传入IO服务,然后创建一个UDP的SOCKET,IPV4版本,端号为13  
  37.     UdpTimeServer(boost::asio::io_service& ioService)  
  38.         :m_sockUdp(ioService,  udp::endpoint(udp::v4(), 13))  
  39.     {  
  40.         //进入接收服务中。  
  41.         RecvTime();  
  42.     }  
  43. private:  
  44.     //接收收客户端的请求。  
  45.     void RecvTime(void)  
  46.     {  
  47.         //异步接收数据  
  48.         m_sockUdp.async_receive_from(  
  49.             boost::asio::buffer(m_recvBuf), m_endpointRemote,  
  50.             boost::bind(&UdpTimeServer::handleRecvTime, this,  
  51.             boost::asio::placeholders::error,  
  52.             boost::asio::placeholders::bytes_transferred));  
  53.     }  
  54.   
  55.     //当收到客户端数据时,就进入本函数响应处理  
  56.     void handleRecvTime(const boost::system::error_code& error,  
  57.         std::size_t /*bytes_transferred*/)  
  58.     {  
  59.         //如果没有出错,就把时间字符串发送给客户端。  
  60.         if (!error || error == boost::asio::error::message_size)  
  61.         {  
  62.             boost::shared_ptr<std::string> strMessage(  
  63.                 new std::string(make_daytime_string()));  
  64.   
  65.             m_sockUdp.async_send_to(boost::asio::buffer(*strMessage), m_endpointRemote,  
  66.                 boost::bind(&UdpTimeServer::handleSendTime, this, strMessage,  
  67.                 boost::asio::placeholders::error,  
  68.                 boost::asio::placeholders::bytes_transferred));  
  69.   
  70.             //接收下一次的信息。  
  71.             RecvTime();  
  72.         }  
  73.     }  
  74.   
  75.     //当发送时间字符串给客户端成功之后响应。  
  76.     void handleSendTime(boost::shared_ptr<std::string> /*strMessage*/,  
  77.             const boost::system::error_code& /*error*/,  
  78.             std::size_t /*bytes_transferred*/)  
  79.     {  
  80.   
  81.     }  
  82.   
  83. private:  
  84.     udp::socket m_sockUdp; //服务器的SOCKET。  
  85.     udp::endpoint m_endpointRemote; //收到数据时的端点信息。  
  86.     boost::array<char, 1> m_recvBuf; //接收数据缓冲区。  
  87. };  
  88.   
  89. void TestUdp(void)  
  90. {  
  91.     boost::asio::io_service ioService;  
  92.     UdpTimeServer udpTimeServer(ioService);  
  93.     ioService.run();  
  94. }  
  95.   
  96.   
  97. int _tmain(int argc, _TCHAR* argv[])  
  98. {  
  99.     //  
  100.     TestUdp();  
  101.   
  102.     return 0;  
  103. }  

在这个例子里,主要封装了一个服务器UdpTimeServer,它是采用io_service对象和socket对象的异步特性来构造,有事件响应之后才去执行相应的操作,不过这样比前面的同步方式,还是复杂了一些,但带来了避免多线程之间的同步问题。

原文地址:https://www.cnblogs.com/lvdongjie/p/4453016.html