這段時間在開發代理服務器,這方面的資料了解的比較多,這里我總結下udp代理服務的實現,也方便我以后查閱。
一、通信模型
1、非代理情況下的通信模型

這是典型的C-S通信模型,客戶端和服務器直接交互。
2、代理情況下的通信模型

這種情況下,服務器和客戶端不是直接交互,而是通過代理服務器進行的,代理服務器負責把客戶端發來的請求轉發給服務器,並把服務的回應返回給客戶端。
二、UDP服務器和客戶端demo
上面分析了通信模型,這里給出一個echo的服務器和客戶端代碼以供下文使用。
1、服務端demo
這里有一個python實現的echo服務器,代碼如下:
#! /usr/bin/python # a simple udp server import socket, traceback s = 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 client import socket,time client = 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)); }
完整代碼:https://gist.github.com/3888929
好,就這些了,希望對你有幫助。
