Решил написать приложение для отладки TCP взаимодействия других приложений и для некой "маршрутизации" трафика. Все просто: мой софт встает между 2х приложений (клиент и сервер) и прозрачно передает данные между ними. Клиент соединяется с моим ПО, а мое ПО соединяется с сервером. Для клиента мое ПО - то же что и сервер, только адрес другой. Для сервера мое ПО - то же что и клиент, только адрес другой. Ну а дальше мое ПО логирует то, что через него проходит. ПО многопоточное. Слушает несколько портов разными потоками + при подключении клиента создает еще один поток, и продолжает слушать дальше. Думал все будет совсем просто. Но столкнулся с трудностями. Вот есть несколько вопросов, подскажите п-та: 1) Как грамотно организовать подключение? Я делаю просто: жду клиента (listen/accept), после подключения создаю еще один поток, ему передаю клиентский сокет, поток открывает сокет с сервером (connect). В этом методе есть один большой минус: если сервер не слушает соответственный порт, мое ПО не может установить TCP соединение, и отключает клиента. Для клиента это выглядит так: он подключается к серверу, который его затем отключает. Если бы моего ПО не было - клиент бы просто не смог подключиться к серверу. Значит мое ПО добавляет какую-то логику, и работа с ним уже не прозрачна. Как это исправить? В идеале, ПО должно понять, что у клиент запросил подключение, затем попытаться соединится с сервером, и по результатам отшить клиента или продолжить работу, установив с ним соединение. 2) Дисконнект клиента/сервера при дисконнекте сервера/клиента. Здесь вообще не ясно. Предположим, ПО соединено и с клиентом и с сервером. В один прекрасный момент сервер отвалился (закрыл сокет). ПО должно сразу же закрыть сокет с клиентом. Но как отследить этот момент??? Я что-то слышал про keepalive, но имхо, это не очень удачный вариант. В моем случае можно отключать и клиента и сервер при отсутствии активности более чем t секунд. 3) Написал кусок кода, который в конечном варианте будет пробрасывать траффик от сервера клиенту и наоборот. Когда у меня один поток - работает на отлично. Но когда потоков много - работает плохо. Теряются пакеты, рвется соединение. А отлаживать несколько потоков весьма сложно. Гляньте, п-та, может я где-то допустил ошибку? Еще раз: этот кусок кода должен пробрасывать траффик между 2мя открытыми сокетами и рвать соединение по таймауту: Код (Text): fd_set remoteServerSocketReadSet; fd_set connectSocketReadSet; timeval readTimeout; readTimeout.tv_sec = 0; readTimeout.tv_usec = 25; // 25 msecks FD_ZERO(&remoteServerSocketReadSet); FD_ZERO(&connectSocketReadSet); FD_SET(params->remoteServerSocket, &remoteServerSocketReadSet); FD_SET(ConnectSocket, &connectSocketReadSet); BOOL optVal; int optLen = sizeof(BOOL); int inactiveCount = INATIVE_COUNT; // initial value while (true){ FD_ZERO(&remoteServerSocketReadSet); FD_ZERO(&connectSocketReadSet); FD_SET(params->remoteServerSocket, &remoteServerSocketReadSet); FD_SET(ConnectSocket, &connectSocketReadSet); // read from client socket if(select(0, &remoteServerSocketReadSet, NULL, NULL, &readTimeout) == 1){ recvLen = recv(params->remoteServerSocket, recvBuffer, BUFF_LEN - 1, 0); if (recvLen != 0){ if((recvLen == SOCKET_ERROR) || (send(ConnectSocket, recvBuffer, recvLen, 0) == SOCKET_ERROR)) break; inactiveCount = INATIVE_COUNT; } } if(select(0, &connectSocketReadSet, NULL, NULL, &readTimeout) == 1){ recvLen = recv(ConnectSocket, recvBuffer, BUFF_LEN - 1, 0); if (recvLen != 0){ if((recvLen == SOCKET_ERROR) || (send(params->remoteServerSocket, recvBuffer, recvLen, 0) == SOCKET_ERROR)) break; inactiveCount = INATIVE_COUNT; } } inactiveCount--; if(inactiveCount <= 0) // if no traffic during timeout break; Sleep(10); } closesocket(params->remoteServerSocket); closesocket(ConnectSocket); Вот такие вот проблемы. Может нужно работать на уровне ниже, чем транспортный??? П.С. Есть приложение TCP Viewer от Westbrook. Вот мне нужно то же самое по функционалу + кое-что от себя. Это приложение работает просто отлично. Спасибо.
Дык а какой тогда оптимальный?? Желательно чтобы код работал быстро. Кстати, глянул TCW Viewer, он не использует select() вообще.