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

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

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

boost库在工作(39)网络UDP异步服务端之九的更多相关文章

  1. TCP/IP网络编程之基于UDP的服务端/客户端

    理解UDP 在之前学习TCP的过程中,我们还了解了TCP/IP协议栈.在四层TCP/IP模型中,传输层分为TCP和UDP这两种.数据交换过程可以分为通过TCP套接字完成的TCP方式和通过UDP套接字完 ...

  2. 【gRPC】C++异步服务端优化版,多服务接口样例

    官方的C++异步服务端API样例可读性并不好,理解起来非常的费劲,各种状态机也并不明了,整个运行过程也容易读不懂,因此此处参考网上的博客进行了重写,以求顺利读懂. C++异步服务端实例,详细注释版 g ...

  3. boost库在工作(37)网络UDP服务端之七

    前面介绍的都是网络TCP的服务器和客户端,其实还有UDP的服务器和客户端,同时也有同步和异步之分.UDP与TCP最大的区别,就是TCP是基于连接的,而UDP是无连接的.这里所谓的连接是指对方中断服务时 ...

  4. boost库在工作(32)网络服务端之二

    在这个例子里,服务器对象主要使用boost::asio::io_service对象,这个对象主要用来构造异步接收数据使用,接着定义boost::asio::ip::tcp::acceptor对象,这个 ...

  5. boost库在工作(36)网络服务端之六

    在上面介绍了管理所有连接的类,这个类主要就是添加新的连接,或者删除不需要的连接.但是管理的类CAllConnect是没有办法知道什么时候添加,什么时候删除的,它需要从接收到连接类里获取得到新的连接,从 ...

  6. boost库在工作(15)绑定器与函数对象之三

    前面已经可以优美地解决两个参数的函数给算法for_each调用了,但是又会遇到这样的一种情况,当需要三个参数或者三个以上的参数给算法for_each调用呢?从STL里的绑定器bind1st,显然是不行 ...

  7. boost库在工作(40)串行通讯

    现代的计算机技术进步很快,各种的通讯也日新月异,像USB.网络.蓝牙.WIFI等通讯技术飞速地出现,改变了整个计算机的通讯能力,速度已经达到GBit级别.但是有一种最原始的通讯方式,还是保留了30年, ...

  8. 第5章-unix网络编程 TCP/服务端程序示例

    这一章主要是完成一个完整的tcp客户/服务器程序.通过一很简单的例子.弄清客户和服务器如何启动,如何终止,发生了某些错误会发生什么.这些事很重要的  客户端代码 #include "unp. ...

  9. Socket 学习(三).2 udp 穿透 服务端 与 客户端 通讯

    之前演示的 是 局域网通讯,也可以用作服务器之间的通讯,不能穿透. 想要穿透就要用 udp 了, 后续再讲解 udp 打洞 . 客户端: using System; using System.Wind ...

随机推荐

  1. thinking in java知识小记(一)

    知识点一(javadoc): 使用javadoc时特别注意选择encoding和charset为utf-8,要不然生成的javadoc会是乱码,命令:javadoc -encoding utf-8 - ...

  2. C#构造函数的 "继承" 问题

    首先说明下 之所以用 双引号 是因为构造函数是没有继承的 派生类默认会调用基类的无参数构造函数 比如: public class A         { public A()         { Co ...

  3. asp net 编程问题 实现下一篇 和上一篇效果

    首先是access数据库,有一个名为news的表,里面有三个字段,分别为id,classid 和name 其中id为主键,classid可以重复 现在有以下数据: id classid name 1 ...

  4. jquery悬停tab2

    <style> *{ margin:0; padding:0;} body { font:12px/19px Arial, Helvetica, sans-serif; color:#66 ...

  5. hdu3714 三分

    Error Curves Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  6. 宏定义中使用do{}while(0)的好处 (转载)

    宏定义中使用do{}while(0)的好处   #define MACRO_NAME(para) do{macro content}while(0)   的格式,总结了以下几个原因:   1,空的宏定 ...

  7. (原)python中import caffe提示no module named google.protobuf.internal

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5993405.html 之前在一台台式机上在python中使用import caffe时,没有出错.但是 ...

  8. Form 表单常用正则验证 (收藏)

    1.^\d+$ //匹配非负整数(正整数 + 0) 2.^[0-9]*[1-9][0-9]*$ //匹配正整数 3.^((-\d+)|(0+))$ //匹配非正整数(负整数 + 0) 4.^-[0-9 ...

  9. 使用 OpenWrt Image Generator 为 WR703N 路由器定制固件

    标题:使用 OpenWrt Image Generator 为 WR703N 路由器定制固件 之前试着自己编译固件,编译是成功了,但是在后期安装官方仓库的ipk时出现问题,因为自己编译的固件和官方固件 ...

  10. [转]详解AppDelegate/UIApplication

    一.UIApplication 1.简单介绍 (1)UIApplication对象是应用程序的象征,一个UIApplication对象就代表一个应用程序. (2)每一个应用都有自己的UIApplica ...