Привет, сетевой друг!
Сегодня продолжим обсуждать инструмент wsock-trace. Разберем, как использовать инструмент на деле.
🟣Подключаем библиотеку правильно: Вместо стандартной ws2_32.lib приложение нужно линковать с wsock-trace:
wsock_trace-x64.lib // для x64
wsock_trace-x86.lib // для x86
Сборка выполняется из каталога src:
nmake -f makefile.vc6
Критично, чтобы бинарь собирался с debug-символами:
cl /Zi /Zo source.c wsock_trace-x64.lib
link /debug
Без PDB стек вызовов и строки кода восстановлены не будут.
🟣Смотрим инициализацию сетевого стека: Первое, что видно в трейсе - реальный момент старта Winsock:
WSAStartup(MAKEWORD(2,2), &wsa);
В выводе сразу видно, где именно в коде произошёл вызов, и не инициализируется ли стек несколько раз разными библиотеками.
🟣Анализируем создание и настройку сокетов. Создание сокета:
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Перевод в неблокирующий режим:
ioctlsocket(sock, FIONBIO, &mode);
Установка опций:
setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
setsockopt(sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
wsock-trace сразу показывает неверные аргументы, которые в обычных логах не видны.
🟣Диагностика зависших connect и select. Установка соединения:
connect(sock, (struct sockaddr*)&addr, sizeof(addr));
Работа с ожиданием событий:
select(nfds, &readfds, &writefds, NULL, &timeout);
FD_ISSET(sock, &readfds);
В трейсе видно, был ли WSAEWOULDBLOCK, какие fd реально готовы и почему код застрял в ожидании, хотя «по логике» не должен.
🟣Передача данных и тайминги. Отправка и приём:
send(sock, buf, len, 0);
recv(sock, buf, len, 0);
recvfrom(sock, buf, len, 0, &from, &fromlen);
Каждый вызов сопровождается точным таймстемпом через QueryPerformanceCounter, количеством байт и направлением трафика. Это позволяет увидеть, где именно появляются задержки.
При необходимости можно искусственно замедлить сеть через конфиг:
recv_delay = 50
send_delay = 20
Серверная Админа | #Инструмент
