博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Boost实现简单的udp代理服务器
阅读量:5966 次
发布时间:2019-06-19

本文共 5526 字,大约阅读时间需要 18 分钟。

这段时间在开发代理服务器,这方面的资料了解的比较多,这里我总结下udp代理服务的实现,也方便我以后查阅。

一、通信模型

1、非代理情况下的通信模型

这是典型的C-S通信模型,客户端和服务器直接交互。

2、代理情况下的通信模型

这种情况下,服务器和客户端不是直接交互,而是通过代理服务器进行的,代理服务器负责把客户端发来的请求转发给服务器,并把服务的回应返回给客户端。

二、UDP服务器和客户端demo

上面分析了通信模型,这里给出一个echo的服务器和客户端代码以供下文使用。

1、服务端demo

这里有一个python实现的echo服务器,代码如下:

#! /usr/bin/python# a simple udp serverimport socket, tracebacks = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)s.bind(("192.168.1.100",12345))while True:    try:        message, address = s.recvfrom(1024)        print "Got data from", address        print message        s.sendto(message, address)    except (KeyboardInterrupt, SystemExit):        raise    except:        traceback.print_exc()

服务端把收到的数据输出并发给客户端。

2、客户端demo 

#! /usr/bin/python# a simple udp clientimport socket,timeclient = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)client.connect(('192.168.1.100', 12345))while True:        client.sendall('3')        print time.time(),' : send success'        print time.time()," : ",client.recv(1024)        time.sleep(3)#client.close()

 客户端负责给服务端发数据并接收服务器返回的数据。

三、UDP代理服务器demo

这里采用boost库实现,用asio中的异步机制。

1、成员变量及参数说明

类名称:m_udpProxyServer

私有成员:

ip::udp::socket downstream_socket_; //代理服务器和客户端的链接

ip::udp::socket upstream_socket_; //代理服务器和远端服务器(echo server)的链接

string _remotehost; // 远端服务器(echo server)的ip地址

int _remoteport; //远端服务器(echo server)的端口

ip::udp::endpoint downstream_remoteUdpEndpoint; //客户端信息

ip::udp::endpoint upstream_remoteUdpEndpoint; //服务端信息

unsigned char downstream_data_[max_data_length]; //上传链路buffer

unsigned char upstream_data_[max_data_length]; //下载链路buffer

2、启动本地服务

代理服务器在这个模型中既充当客户端的服务器,又充当远端服务器(echo server)的客户端,所以代理服务器既要有本地监听端口供客户端连接,又要向远端服务器(echo server)发起链接,转发客户端发来的数据。

View Code
m_udpProxyServer(io_service& io,const string& localhost,    const int& localport,const string& remotehost,const int& remoteport):    downstream_socket_(io,ip::udp::endpoint(ip::udp::v4(),localport)), //启动本地服务    upstream_socket_(io), //初始化连接远端服务器的socket    _remotehost(remotehost),    _remoteport(remoteport),    upstream_remoteUdpEndpoint(ip::address_v4::from_string(_remotehost),_remoteport)    {        start_downstream_receive();    }

3、连接远端服务器

当接收到客户端发来的数据后,触发代理服务器向远端服务器的连接。

View Code
//接收客户端发来的数据void start_downstream_receive(){    //如果接收到客户端的数据则触发向服务器的链接    downstream_socket_.async_receive_from(        boost::asio::buffer(downstream_data_,max_data_length),        downstream_remoteUdpEndpoint,        boost::bind(&m_udpProxyServer::upstream_connect,this,         boost::asio::placeholders::bytes_transferred,        boost::asio::placeholders::error));}//连接远端服务器void upstream_connect(const size_t& bytes_transferred,    const boost::system::error_code& error){        if (!error )    {            upstream_socket_.async_connect(            upstream_remoteUdpEndpoint,            boost::bind(&m_udpProxyServer::handle_upstream_connect,            this,bytes_transferred,boost::asio::placeholders::error));            }    else    {        std::cerr << "Error: " << error.message() << std::endl;    }}

4、数据转发

将从客户端接收到的数据转发给远端服务器,并接收远端服务器的返回数据,转发给客户端。

View Code
void handle_upstream_connect(const size_t& bytes_transferred,    const boost::system::error_code& error){    //将从客户端接收到的数据转发给远端服务器    upstream_socket_.async_send_to(            boost::asio::buffer(downstream_data_,bytes_transferred),            upstream_remoteUdpEndpoint,            boost::bind(&m_udpProxyServer::handle_upstream_send,            this,boost::asio::placeholders::error));}void handle_upstream_send(const boost::system::error_code& error){    if (!error )    {                //从服务器接收返回数据        upstream_socket_.async_receive_from(            boost::asio::buffer(upstream_data_,max_data_length),            upstream_remoteUdpEndpoint,            boost::bind(&m_udpProxyServer::handle_upstream_receive,            this,                                boost::asio::placeholders::bytes_transferred,            boost::asio::placeholders::error));    }    else    {        std::cerr << "Error: " << error.message() << std::endl;    }}void handle_upstream_receive(const size_t& bytes_transferred,    const boost::system::error_code& error){    if (!error )    {                    //把从服务器接收到的返回数据转发给客户端        downstream_socket_.async_send_to(            boost::asio::buffer(upstream_data_,bytes_transferred),            downstream_remoteUdpEndpoint,            boost::bind(&m_udpProxyServer::handle_downstream_send,            this,            boost::asio::placeholders::error));    }    else    {        std::cerr << "Error: " << error.message() << std::endl;    }}void handle_downstream_send(const boost::system::error_code& error){    if (!error )    {                //接收客户端发来的数据        downstream_socket_.async_receive_from(            boost::asio::buffer(downstream_data_,max_data_length),            downstream_remoteUdpEndpoint,            boost::bind(&m_udpProxyServer::handle_downstream_receive,this,            boost::asio::placeholders::bytes_transferred,            boost::asio::placeholders::error));    }    else    {        std::cerr << "Error: " << error.message() << std::endl;    }}void handle_downstream_receive(const size_t& bytes_transferred,    const boost::system::error_code& error){    //将从客户端接收到的数据转发给远端服务器    upstream_socket_.async_send_to(        boost::asio::buffer(downstream_data_,bytes_transferred),        upstream_remoteUdpEndpoint,        boost::bind(&m_udpProxyServer::handle_upstream_send,        this,boost::asio::placeholders::error));}

完整代码:

好,就这些了,希望对你有帮助。

转载地址:http://vctax.baihongyu.com/

你可能感兴趣的文章
pdo 连接数据库 报错 could not find driver 解决方法
查看>>
设计模式之策略模式
查看>>
JVM介绍
查看>>
Qt中使用QToolBox实现抽屉效果
查看>>
双活数据中心建设之光大实践
查看>>
张军-大数据的理解与分布式进化计算方法
查看>>
dubbo remoting(2)
查看>>
maya pyside 多个窗口实例 报错 解决
查看>>
关于文件上传请求第一次为post,后面为get的问题
查看>>
【Qt笔记】QDialog--模态和非模态
查看>>
nginx 0.8.54/1.0.0 在cygwin环境下的编译(包括 nginx_mod_h264
查看>>
PowerDesigner生成Excel版本的数据库文件
查看>>
Oracle 查找常见耗性能的语句
查看>>
thinkphp 开启页面的Trace信息
查看>>
mysql 链接数满了的错误 ERROR 1040 (HY000): Too many connections
查看>>
android textview字体加下划线
查看>>
springMVC 定时任务
查看>>
Mint8(ubuntu16.04) 搭建微信Web开发工具
查看>>
PostgreSQL数据类型-数据类型简介和布尔类型
查看>>
PostgreSQL数据类型-二进制数据和字符串数据类型与字符串函数
查看>>