2

標準ソケットを使用した次のコードがあります。

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

ソケット クライアントと conn があり、それらの間のトラフィックを「プロキシ」する必要があります (これは、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))、ブラウザ クライアントからのデータをソックス プロキシ経由で読み取ることができるが、上記の ProxySession::Start のバージョンでは、どのような状況でも HandleProxyRead が呼び出されないことです。

ここでデータを交換する非同期の方法は本当に必要ありません。それは、ここでこのソリューションを思いついたということだけです。また、ProxySession->start from code を呼び出した場所から、スリープを導入する必要がありました。そうしないと、これが実行されていたスレッド コンテキストがシャットダウンされていたからです。

*更新 2 *以下の私の更新の 1 つを参照してください。質問ブロックが大きくなりすぎています。

4

2 に答える 2

1

この問題は、非同期の書き込み/読み取り関数を使用して、提示されたコードと同様のものを使用することで解決できます。基本的に async_read_some()/async_write() またはこれらのカテゴリの他の非同期関数を使用します。また、非同期処理を機能させるには、非同期処理の完了ハンドラをディスパッチする boost::asio::io_service.run() を呼び出す必要があります。

于 2012-01-29T09:53:54.633 に答える
0

私はこれでなんとかやって来ました。このソリューションは、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;
    }
于 2012-01-28T10:41:24.870 に答える