Есть 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));
}
Это хорошее решение, но с доп. потоком. Хочется решения идеального без доп. потока.