#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 (или ошибку).