boost asio - 编写等效的代码段

发布于 2024-12-29 08:41:13 字数 2836 浏览 6 评论 0 原文

我有这段使用标准套接字的代码:

void set_fds(int sock1, int sock2, fd_set *fds) {
    FD_ZERO (fds);
    FD_SET (sock1, fds); 
    FD_SET (sock2, fds); 
}

void do_proxy(int client, int conn, char *buffer) {
    fd_set readfds; 
    int result, nfds = max(client, conn)+1;
    set_fds(client, conn, &readfds);
    while((result = select(nfds, &readfds, 0, 0, 0)) > 0) {
        if (FD_ISSET (client, &readfds)) {
            int recvd = recv(client, buffer, 256, 0);
            if(recvd <= 0)
                return;
            send_sock(conn, buffer, recvd);
        }
        if (FD_ISSET (conn, &readfds)) {
            int recvd = recv(conn, buffer, 256, 0);
            if(recvd <= 0)
                return;
            send_sock(client, buffer, recvd);
        }
        set_fds(client, conn, &readfds);
    }

我有套接字客户端和连接器,我需要“代理”它们之间的流量(这是socks5服务器实现的一部分,您可能会看到https://github.com/mfontanini/Programs-Scripts/blob/master/socks5/socks5.cpp)。我怎样才能在 asio 下实现这一目标?

我必须指出,到目前为止,两个套接字都在阻塞模式下运行。

尝试使用此方法但没有成功:

ProxySession::ProxySession(ba::io_service& ioService, socket_ptr socket, socket_ptr clientSock): ioService_(ioService), socket_(socket), clientSock_(clientSock)
{

}

void ProxySession::Start()
{
    socket_->async_read_some(boost::asio::buffer(data_, 1),
        boost::bind(&ProxySession::HandleProxyRead, this,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred));    
}

void ProxySession::HandleProxyRead(const boost::system::error_code& error,
      size_t bytes_transferred)
{
    if (!error)
    {
      boost::asio::async_write(*clientSock_,
          boost::asio::buffer(data_, bytes_transferred),
          boost::bind(&ProxySession::HandleProxyWrite, this,
            boost::asio::placeholders::error));
    }
    else
    {
      delete this;
    }
}


void ProxySession::HandleProxyWrite(const boost::system::error_code& error)
{
   if (!error)
    {
       socket_->async_read_some(boost::asio::buffer(data_, max_length),
        boost::bind(&ProxySession::HandleProxyRead, this,
          boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred));
    }
    else
    {
      delete this;
    }
}

问题是,如果我执行 ba::read(*socket_, ba::buffer(data_,256)) 我可以读取数据通过socks代理来自我的浏览器客户端,但在上面的版本中ProxySession::Start在任何情况下都不会导致HandleProxyRead被调用。

我真的不需要在这里交换数据的异步方式,只是我在这里提出了这个解决方案。另外,从我调用 ProxySession->start from code 的地方,我需要引入睡眠,否则执行此操作的线程上下文将被关闭。

*更新 2 * 请参阅下面我的更新之一。问题块变得太大了。

I have this piece of code using standard sockets:

void set_fds(int sock1, int sock2, fd_set *fds) {
    FD_ZERO (fds);
    FD_SET (sock1, fds); 
    FD_SET (sock2, fds); 
}

void do_proxy(int client, int conn, char *buffer) {
    fd_set readfds; 
    int result, nfds = max(client, conn)+1;
    set_fds(client, conn, &readfds);
    while((result = select(nfds, &readfds, 0, 0, 0)) > 0) {
        if (FD_ISSET (client, &readfds)) {
            int recvd = recv(client, buffer, 256, 0);
            if(recvd <= 0)
                return;
            send_sock(conn, buffer, recvd);
        }
        if (FD_ISSET (conn, &readfds)) {
            int recvd = recv(conn, buffer, 256, 0);
            if(recvd <= 0)
                return;
            send_sock(client, buffer, recvd);
        }
        set_fds(client, conn, &readfds);
    }

I have sockets client and conn and I need to "proxy" traffic between them (this is part of a socks5 server implementation, you may see https://github.com/mfontanini/Programs-Scripts/blob/master/socks5/socks5.cpp). How can I achieve this under asio ?

I must specify that until this point both sockets were operated under blocking mode.

Tried to use this without success:

ProxySession::ProxySession(ba::io_service& ioService, socket_ptr socket, socket_ptr clientSock): ioService_(ioService), socket_(socket), clientSock_(clientSock)
{

}

void ProxySession::Start()
{
    socket_->async_read_some(boost::asio::buffer(data_, 1),
        boost::bind(&ProxySession::HandleProxyRead, this,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred));    
}

void ProxySession::HandleProxyRead(const boost::system::error_code& error,
      size_t bytes_transferred)
{
    if (!error)
    {
      boost::asio::async_write(*clientSock_,
          boost::asio::buffer(data_, bytes_transferred),
          boost::bind(&ProxySession::HandleProxyWrite, this,
            boost::asio::placeholders::error));
    }
    else
    {
      delete this;
    }
}


void ProxySession::HandleProxyWrite(const boost::system::error_code& error)
{
   if (!error)
    {
       socket_->async_read_some(boost::asio::buffer(data_, max_length),
        boost::bind(&ProxySession::HandleProxyRead, this,
          boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred));
    }
    else
    {
      delete this;
    }
}

The issue is that if I do ba::read(*socket_, ba::buffer(data_,256)) I can read data that comes from my browser client through socks proxy but in the version from above ProxySession::Start does not lead to HandleProxyRead being called in any circumstances.

I don't really need an async way of exchanging data here, it;s just that I've come by with this solution here. Also from where I called ProxySession->start from code I needed to introduce a sleep because otherwise the thread context from which this was executing was being shut down.

*Update 2 * See below one of my updates. The question block is getting too big.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

囍笑 2025-01-05 08:41:13

该问题可以通过使用异步写/读函数来解决,以便与所提供的代码具有类似的功能。基本上使用 async_read_some()/async_write() - 或这些类别中的其他异步函数。另外,为了使异步处理正常工作,必须调用 boost::asio::io_service.run() ,它将为异步处理调度完成处理程序。

The problem ca be solved by using asynchronous write/read functions in order to have something similar with presented code. Basically use async_read_some()/async_write() - or other async functions in these categories. Also in order for async processing to work one must call boost::asio::io_service.run() that will dispatch completion handler for async processing.

沫尐诺 2025-01-05 08:41:13

我已经成功做到了这一点。该解决方案解决了2个套接字的“数据交换”问题(根据socks5服务器代理,这必须发生),但它的计算量很大。有什么想法吗?

std::size_t readable = 0;

    boost::asio::socket_base::bytes_readable command1(true);
    boost::asio::socket_base::bytes_readable command2(true);


    try 
    {
        while (1)
        {
            socket_->io_control(command1);
            clientSock_->io_control(command2);

            if ((readable = command1.get()) > 0)
            {
                transf = ba::read(*socket_, ba::buffer(data_,readable));
                ba::write(*clientSock_, ba::buffer(data_,transf));
                boost::this_thread::sleep(boost::posix_time::milliseconds(500));
            }

            if ((readable = command2.get()) > 0)
            {
                transf = ba::read(*clientSock_, ba::buffer(data_,readable));
                ba::write(*socket_, ba::buffer(data_,transf));
                boost::this_thread::sleep(boost::posix_time::milliseconds(500));
            }
        }
    }
    catch (std::exception& ex)
    {
        std::cerr << "Exception in thread while exchanging: " << ex.what() << "\n";
        return;
    }

I have managed to come with this. This solution solves the problem of "data exchange" for the 2 sockets (that must happen acording to socks5 server proxy) but it is very compute intensive. Any ideas ?

std::size_t readable = 0;

    boost::asio::socket_base::bytes_readable command1(true);
    boost::asio::socket_base::bytes_readable command2(true);


    try 
    {
        while (1)
        {
            socket_->io_control(command1);
            clientSock_->io_control(command2);

            if ((readable = command1.get()) > 0)
            {
                transf = ba::read(*socket_, ba::buffer(data_,readable));
                ba::write(*clientSock_, ba::buffer(data_,transf));
                boost::this_thread::sleep(boost::posix_time::milliseconds(500));
            }

            if ((readable = command2.get()) > 0)
            {
                transf = ba::read(*clientSock_, ba::buffer(data_,readable));
                ba::write(*socket_, ba::buffer(data_,transf));
                boost::this_thread::sleep(boost::posix_time::milliseconds(500));
            }
        }
    }
    catch (std::exception& ex)
    {
        std::cerr << "Exception in thread while exchanging: " << ex.what() << "\n";
        return;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文