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();
}
相关推荐
游戏开发爱好者81 小时前
iOS重构期调试实战:架构升级中的性能与数据保障策略
websocket·网络协议·tcp/ip·http·网络安全·https·udp
森焱森2 小时前
水下航行器外形分类详解
c语言·单片机·算法·架构·无人机
小殷学长4 小时前
【单片机毕业设计17-基于stm32c8t6的智能倒车监测系统】
stm32·单片机·课程设计
TESmart碲视6 小时前
HKS201-M24 大师版 8K60Hz USB 3.0 适用于 2 台 PC 1台显示器 无缝切换 KVM 切换器
单片机·嵌入式硬件·物联网·游戏·计算机外设·电脑·智能硬件
花落已飘7 小时前
STM32中实现shell控制台(shell窗口输入实现)
stm32·单片机·嵌入式硬件
DemonAvenger8 小时前
高性能 TCP 服务器的 Go 语言实现技巧:从原理到实践
网络协议·架构·go
牵牛老人9 小时前
Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用
stm32·单片机·qt
趙卋傑9 小时前
TCP/UDP
udp·tcp·tcp核心机制
宇钶宇夕10 小时前
针对工业触摸屏维修的系统指南和资源获取途径
单片机·嵌入式硬件·自动化
和风化雨11 小时前
stm32的三种开发方式
stm32·单片机·嵌入式硬件