boost asio - написать эквивалентный кусок кода - PullRequest
2 голосов
/ 28 января 2012

У меня есть этот кусок кода с использованием стандартных сокетов:

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)), я смогу читать данные, которые поступают из моего клиента браузера через прокси-сервер socks, но в версии выше ProxySession :: Start не приводит к вызову HandleProxyRead при любых обстоятельствах.

Мне действительно не нужен асинхронный способ обмена данными, просто я пришел с этим решением здесь. Кроме того, откуда я вызывал ProxySession-> start из кода, мне нужно было ввести спящий режим, потому что в противном случае контекст потока, из которого это выполнялось, был закрыт.

* Обновление 2 * См. Ниже одно из моих обновлений. Блок вопросов становится слишком большим.

Ответы [ 2 ]

1 голос
/ 29 января 2012

Проблема может быть решена с помощью асинхронных функций записи / чтения, чтобы иметь что-то похожее с представленным кодом.В основном используйте async_read_some () / async_write () - или другие асинхронные функции в этих категориях.Также, чтобы асинхронная обработка работала, необходимо вызвать boost :: asio :: io_service.run (), который отправит обработчик завершения асинхронной обработки.

0 голосов
/ 28 января 2012

Мне удалось прийти с этим. Это решение решает проблему «обмена данными» для двух сокетов (что должно происходить в соответствии с прокси-сервером 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;
    }
...