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();
}
相关推荐
石牌桥网管42 分钟前
OpenSSL 生成根证书、中间证书和网站证书
网络协议·https·openssl
scan12 小时前
单片机串口接收状态机STM32
stm32·单片机·串口·51·串口接收
Qingniu012 小时前
【青牛科技】应用方案 | RTC实时时钟芯片D8563和D1302
科技·单片机·嵌入式硬件·实时音视频·安防·工控·储能
深圳市青牛科技实业有限公司4 小时前
【青牛科技】应用方案|D2587A高压大电流DC-DC
人工智能·科技·单片机·嵌入式硬件·机器人·安防监控
Mr.谢尔比5 小时前
电赛入门之软件stm32keil+cubemx
stm32·单片机·嵌入式硬件·mcu·信息与通信·信号处理
LightningJie5 小时前
STM32中ARR(自动重装寄存器)为什么要减1
stm32·单片机·嵌入式硬件
西瓜籽@5 小时前
STM32——毕设基于单片机的多功能节能窗控制系统
stm32·单片机·课程设计
阿尔帕兹7 小时前
构建 HTTP 服务端与 Docker 镜像:从开发到测试
网络协议·http·docker
远翔调光芯片^138287988728 小时前
远翔升压恒流芯片FP7209X与FP7209M什么区别?做以下应用市场摄影补光灯、便携灯、智能家居(调光)市场、太阳能、车灯、洗墙灯、舞台灯必看!
科技·单片机·智能家居·能源
FeelTouch Labs8 小时前
Netty实现WebSocket Server是否开启压缩深度分析
网络·websocket·网络协议