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


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

    // boost_028.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <ctime>
    
    #include <boost/asio/ip/tcp.hpp>
    #include <boost/asio.hpp>
    #include <boost/bind.hpp>
    #include <boost/enable_shared_from_this.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/array.hpp>
    
    #include <iostream>
    #include <string>
    
    //使用UDP命名空间
    using boost::asio::ip::udp;
    
    //把当前时间转换为字符串。
    std::string make_daytime_string()
    {
    	using namespace std; //为了使用time_t, time 和 ctime;
    	time_t now = time(0);
    	return ctime(&now);
    }
    
    //
    //创建一个异步UDP的时间服务器。
    //软件开发人员: 蔡军生  2013-08-25 
    //QQ: 9073204
    //
    class UdpTimeServer
    {
    public:
    	//传入IO服务,然后创建一个UDP的SOCKET,IPV4版本,端号为13
    	UdpTimeServer(boost::asio::io_service& ioService)
    		:m_sockUdp(ioService,  udp::endpoint(udp::v4(), 13))
    	{
    		//进入接收服务中。
    		RecvTime();
    	}
    private:
    	//接收收客户端的请求。
    	void RecvTime(void)
    	{
    		//异步接收数据
    		m_sockUdp.async_receive_from(
    			boost::asio::buffer(m_recvBuf), m_endpointRemote,
    			boost::bind(&UdpTimeServer::handleRecvTime, this,
    			boost::asio::placeholders::error,
    			boost::asio::placeholders::bytes_transferred));
    	}
    
    	//当收到客户端数据时,就进入本函数响应处理
    	void handleRecvTime(const boost::system::error_code& error,
    		std::size_t /*bytes_transferred*/)
    	{
    		//如果没有出错,就把时间字符串发送给客户端。
    		if (!error || error == boost::asio::error::message_size)
    		{
    			boost::shared_ptr<std::string> strMessage(
    				new std::string(make_daytime_string()));
    
    			m_sockUdp.async_send_to(boost::asio::buffer(*strMessage), m_endpointRemote,
    				boost::bind(&UdpTimeServer::handleSendTime, this, strMessage,
    				boost::asio::placeholders::error,
    				boost::asio::placeholders::bytes_transferred));
    
    			//接收下一次的信息。
    			RecvTime();
    		}
    	}
    
    	//当发送时间字符串给客户端成功之后响应。
    	void handleSendTime(boost::shared_ptr<std::string> /*strMessage*/,
    			const boost::system::error_code& /*error*/,
    			std::size_t /*bytes_transferred*/)
    	{
    
    	}
    
    private:
    	udp::socket m_sockUdp; //服务器的SOCKET。
    	udp::endpoint m_endpointRemote; //收到数据时的端点信息。
    	boost::array<char, 1> m_recvBuf; //接收数据缓冲区。
    };
    
    void TestUdp(void)
    {
    	boost::asio::io_service ioService;
    	UdpTimeServer udpTimeServer(ioService);
    	ioService.run();
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	//
    	TestUdp();
    
    	return 0;
    }
    

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


  • 相关阅读:
    [两个数]最大公约(因)数和最小公倍数
    【curl】【php】curl报错,错误代码77,CURLE_SSL_CACERT_BADFILE (77)解决方法
    【杂项】【旅行】旅行必备
    【windows】【php】【nginx】windows 开机自启动nginx php 及nginx php配置
    【mysql】linux, mac mysql数据库root 密码忘记修改
    【mysql】 load local data infield 报错 ERROR 1148 (42000): The used command is not allowed with this MySQL version
    【mysql】配置 选项文件
    【发布相关】【心得体会】发布的注意事项-20180921
    【php】【运算符】位移运算符
    【php】运算符优先级界定
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3295222.html
Copyright © 2020-2023  润新知