Корректное завершение работы сокета TCP

#c #sockets #tcp #winsock #irc

#c #сокеты #tcp #winsock #irc

Вопрос:

Я пишу IRC-клиент на C , и в настоящее время у меня возникает проблема, при выходе из которой я:

Отправить("QUIT :Quit r  n"); // просто встроенная обертка с переменной отправкой() 
завершение работы (m_hSocket, SD_BOT);
closesocket(m_hSocket);

WSAShutdown();

Однако проблема заключается в том, что сообщение о завершении не отправляется. Я прослушал пакеты, поступающие от клиента, и фактически это сообщение никогда не отправляется. Я полагаю, что это проблема с тем, что сокет не сбрасывается, но я понятия не имею, как это сделать, и Google предложил отключить алгоритм Нейгла, но я сомневаюсь, что это хорошая практика.

Заранее спасибо.

Комментарии:

1. Когда вы все-таки заставите это работать, помните, что некоторые IRC-сети не будут показывать пользовательское сообщение о выходе, пока вы не войдете в систему в течение > 5 минут (фактическая продолжительность варьируется в зависимости от сети). Это не ответ на вашу текущую проблему, но это ошибка, которая может сбить с толку позже 🙂

2. Интересный момент, но я уже пару раз сталкивался с этим, вышел и все еще получаю: Ошибка чтения: Сброс соединения одноранговым узлом

3. да, я просто подумал, что упомяну об этом, когда вы исправите проблему с сокетом 🙂

4. Для сокетов не выполняется операция сброса. Небольшие данные собираются в течение примерно 40 мс, а затем отправляются. Это называется алгоритмом Наггла.

Ответ №1:

Прежде всего, вы должны проверить возвращаемое значение send : действительно ли данные, которые вы пытаетесь отправить, принимаются сетевым стеком? (В общем, это следует делать после каждого send вызова, а не только в этом случае).

Предполагая, что данные приняты, тогда AFAIK они должны быть фактически переданы в результате вызова shutdown . Вы можете попробовать использовать SO_LINGER , чтобы увидеть, имеет ли это значение, см. «Корректное завершение работы», «Параметры задержки» и «Закрытие сокета» в MSDN.

Комментарии:

1. Даже используя исправление в комментариях к этой статье MSDN, я все еще получаю ошибку при закрытии сокетов при выходе. Кажется, WSACleanup() вызывает это. В любом случае, спасибо, Джон! 😀

2. После вызова shutdown() вы не должны вызывать closesocket() до тех пор, пока удаленный одноранговый узел не подтвердит запрос на отключение, вызывая recv() в цикле (необязательно с select() указанием времени вызова recv() ), пока он не вернет 0 (или ошибку).