Boost實現簡單的udp代理服務器


這段時間在開發代理服務器,這方面的資料了解的比較多,這里我總結下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

好,就這些了,希望對你有幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM