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();
}