boost::asio проксирование tcp сессии
От: whitenigga  
Дата: 04.01.13 03:36
Оценка:
Есть 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)  //здесь мы ждём, пока на любой из 2-х сокетов прилетят данные
    {
        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);
    }
}


Как сделать тоже самое, на boost::asio? То есть нужен аналог select, который блокирует поток до тех пор пока на 1-й или 2-й сокет (boost::asio::ip::tcp::socket) не поступят данные, ну или оборвётся связь и т.п.

Знаю что можно решить проблему с помощью 2-х потоков и эхо сервером в каждом (1 поток — эхо сервер 1сокет->2сокет; 2 поток — эхо сервер 2сокет->1сокет).
Код примерно такой:

while(1)
{
    char data[max_length];

    size_t length = psock->read_some(boost::asio::buffer(data), error);
    if(error == boost::asio::error::eof)
        break; // Connection closed cleanly by peer.
    else if (error)
        throw boost::system::system_error(error); // Some other error.

    boost::asio::write(*psock, boost::asio::buffer(data, length));
}


Это хорошее решение, но с доп. потоком. Хочется решения идеального без доп. потока.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.