udp 代理转发的代码

udp 代理转发的代码

c 复制代码
#include <string.h>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/bind/bind.hpp>
#include <boost/thread.hpp>
#include <mutex>
#include <string>
#include <unordered_map>
using namespace std;
using namespace boost;
using namespace boost::asio;
using boost::asio::ip::udp;

struct s_send {
	//uint16_t _port;
	//udp::socket _socket ;
	asio::io_context& v_con;
	ip::udp::socket v_sock ;
	//recv
	uint64_t recv_bytes = 0;
	uint8_t buf[1500] = {0};
	s_send(asio::io_context& io):v_con(io),v_sock(v_con, udp::v4())
	{
		//v_sock = new ip::udp::socket(ctx);
	}
	~s_send()
	{
		if (v_sock.is_open())
		{
			v_sock.cancel();
		}
	}
};
typedef std::shared_ptr<s_send> ptr_send;

class udp_proxy:public std::enable_shared_from_this<udp_proxy>
{
	std::unordered_map<std::string, ptr_send> v_map_sockets;
#define MTU_LEN 1500
	ip::udp::socket server_socket_;   //接收客户端的链接

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

	string up_host_; // 远端服务器ip地址

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

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

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

	unsigned char down_data_[MTU_LEN]; //上传链路buffer

	unsigned char up_data_[MTU_LEN]; //下载链路buffer

public:
	udp_proxy(io_service& io, const string& localhost,
		const int& localport, const string& remotehost, const int& remoteport) :
		server_socket_(io, ip::udp::endpoint(ip::udp::v4(), localport)), //启动本地服务
		upstream_socket_(io), //初始化连接远端服务器的socket
		up_host_(remotehost),
		up_port_(remoteport),
		v_io_con(io),
		v_strand(io.get_executor()),
		upstream_remoteUdpEndpoint(ip::address_v4::from_string(remotehost), remoteport)
	{
		boost::asio::socket_base::receive_buffer_size size_option_r(4 * 1024 * 1024);
		server_socket_.set_option(size_option_r);
		
		go();

		//start_receive();
	}

	void start_receive()
	{
		//如果接收到客户端的数据则触发向服务器的链接
		server_socket_.async_receive_from(
			boost::asio::buffer(down_data_, MTU_LEN),
			downstream_remoteUdpEndpoint,
			boost::bind(&udp_proxy::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(&udp_proxy::handle_upstream_connect,
					this, bytes_transferred, boost::asio::placeholders::error));
		}
		else
		{
			std::cerr << "Error: " << error.message() << std::endl;
		}
	}


    void handle_upstream_connect(const size_t& bytes_transferred,
        const boost::system::error_code& error)
    {
        //将从客户端接收到的数据转发给远端服务器
        upstream_socket_.async_send_to(
            boost::asio::buffer(down_data_, bytes_transferred),
            upstream_remoteUdpEndpoint,
            boost::bind(&udp_proxy::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(up_data_, MTU_LEN),
                upstream_remoteUdpEndpoint,
                boost::bind(&udp_proxy::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)
        {
            //把从服务器接收到的返回数据转发给客户端
            server_socket_.async_send_to(
                boost::asio::buffer(up_data_, bytes_transferred),
                downstream_remoteUdpEndpoint,
                boost::bind(&udp_proxy::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)
        {
            //接收客户端发来的数据
            server_socket_.async_receive_from(
                boost::asio::buffer(down_data_, MTU_LEN),
                downstream_remoteUdpEndpoint,
                boost::bind(&udp_proxy::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(down_data_, bytes_transferred),
            upstream_remoteUdpEndpoint,
            boost::bind(&udp_proxy::handle_upstream_send,
                this, boost::asio::placeholders::error));
    }

	boost::asio::strand<boost::asio::io_context::executor_type> v_strand;

	asio::io_context& v_io_con;




	bool func_hand_shake(boost::asio::yield_context& yield)
	{
		//boost::lexical_cast<string>(boost::this_thread::get_id());
		cout << "thread id:" << boost::this_thread::get_id() << endl;
		//ip::udp::socket up_socket(v_io_con);
		boost::system::error_code ec;
		boost::asio::ip::udp::endpoint sendp;

		//server_socket_.async_receive_from(asio::null_buffers(), sendp, yield[ec]);
		//buffer.resize(socket_->available());
		//socket_->receive_from(boost::asio::buffer(buffer), sender_endpoint);

		char buf[1500];
		//size_t n = server_socket_.async_receive_from(asio::buffer(&buf[0], 1500), sendp, yield[ec]);
		//string str = sendp.address().to_string();
		size_t n = server_socket_.async_receive(asio::buffer(&buf[0], 1500), yield[ec]);
		string ip = sendp.address().to_string();
		if (v_map_sockets.find(ip) == v_map_sockets.end())
		{
			//spdlog::info("ip in {0}", ip.c_str());
			ptr_send ptr = std::make_shared<s_send>(v_io_con);
#if 1
			ptr->v_sock.async_connect(upstream_remoteUdpEndpoint, yield[ec]);
			boost::asio::socket_base::send_buffer_size rbs;
			ptr->v_sock.get_option(rbs);
			cout << "send buffer size" << rbs.value() << endl;
			boost::asio::socket_base::send_buffer_size size_option_s(4 * 1024 * 1024);
			ptr->v_sock.set_option(size_option_s);
#endif
			v_map_sockets[ip] = ptr;
		}
		ptr_send& ptr = v_map_sockets[ip];
		if (!ec)
		{
			//boost::asio::ip::udp::socket sock(v_io_con);

			boost::asio::ip::udp::socket& upstream =  ptr->v_sock; //p->_socket;
			
			upstream.async_send(asio::buffer(&buf[0], n), yield[ec]);
			if (ec)
			{
				cout << "write error" << endl;
				return false;
			}
			return true;
			//asio::async_write()
		}
		else
		{
			return false;
		}
	}

	void go()
	{
		//auto self(shared_from_this());
		boost::asio::spawn(v_io_con,
			[this](boost::asio::yield_context yield)
			{
				//try
				//{
					//timer_.expires_from_now(std::chrono::seconds(10));
				for (;;)
				{
					if (func_hand_shake(yield) == false)
					{
						std::cout << "not hand shake" << std::endl;
						break;
					}
				}
			});
	}

};


int main()
{
	io_context io;
	boost::thread_group threads;

	std::shared_ptr<udp_proxy> udp = std::make_shared<udp_proxy>(io, "192.168.0.129", 6000, "192.168.0.129", 7000);
	for (std::size_t i = 0; i < 3; ++i)
	{
		threads.create_thread(
			boost::bind(&boost::asio::io_service::run, &io));
	}
	io.run();
	threads.join_all();
}
相关推荐
每天的积累28 分钟前
面试知识点总结篇二
stm32·单片机·嵌入式硬件·面试
一颗去去1 小时前
【HTTP 和 HTTPS详解】1
网络协议·http·https
Tlog嵌入式2 小时前
蓝桥杯【物联网】零基础到国奖之路:九. I2C
stm32·单片机·mcu·物联网·蓝桥杯·51单片机·iot
嵌入式详谈2 小时前
基于STM32的智能空气质量监测系统
stm32·单片机·嵌入式硬件
青果网络_xz5 小时前
爬虫中,短效IP和长效IP哪个更好用?
服务器·爬虫·网络协议·tcp/ip·http
2401_872514975 小时前
在线代理提取IP:一文详解其含义和应用
服务器·网络·网络协议·tcp/ip·安全
IT WorryFree5 小时前
HP 电脑 - 管理电源选项 (Windows 10)
windows·单片机·电脑
面包板扎6 小时前
51单片机应用开发(进阶)---数码管显示按键“加”“减”计数
单片机·嵌入式硬件·51单片机
修炼室6 小时前
从拥堵到畅通:HTTP/2 如何解决 Web 性能瓶颈?
前端·网络协议·http