Вызов shutdown и closesocket дважды на одном сокете - PullRequest
2 голосов
/ 25 июня 2010

В моем приложении я вызываю функции shutdown и closesocket дважды в одном сокете.Я знаю, что это неправильно, и я должен убедиться, что эти функции вызываются только один раз.Но почему ни один из этих вызовов не завершится неудачно при повторном вызове?

Если дескриптор m_Socket равен 1500, то каким будет его значение, если функции shutdown и closesocketназывается?

shutdown(m_SocServer, 2);
closesocket(m_SocServer);

Ответы [ 3 ]

7 голосов
/ 25 июня 2010

Сначала нужно различить две разные вещи:

  1. Выполнение операций с сокетом, некоторые из которых могут привести его в нерабочее состояние.
  2. Завершение ручки гнезда.

Вызов shutdown с параметром 2 (который SD_BOTH) равен (1). То есть вы сбрасываете весь ожидающий буфер, а также отбрасываете весь буфер приема. Так что вы не можете читать / писать больше. Однако вы все еще держите действительный дескриптор сокета. Вы все еще можете запросить / установить его параметры, если хотите. Например, можно позвонить по номеру getpeername и узнать адрес, к которому вы подключены. Кроме того, в зависимости от реализации, повторный вызов shutdown не должен приводить к ошибке. Может быть, это имеет накопительный эффект.

С другой стороны, вызов closesocket - это (2). Как только вы назвали это - вы ничего не можете сделать с этим дескриптором сокета. Теперь он недействителен.

Если у вашего сокета есть значение 1500 - оно останется, даже после вызова closesocket. Потому что это просто переменная. Это все равно, что спросить, какое значение будет иметь указатель после delete.

Однако это значение сокета (1500) больше недействительно. Вы не можете вызвать любую функцию сокета с этим значением.

Более того, если вы создадите еще один сокет - он, скорее всего, получит тот же номер. Здесь вы можете столкнуться с более серьезной проблемой - выполнять действия на другом сокете, не замечая этого.

В некоторых случаях рекомендуется присваивать значение INVALID_SOCKET переменной сокета сразу после вызова closesocket.

P.S. Возможно, вызов shutdown + closesocket не приведет к ошибке, потому что вы закрываете другой сокет.

5 голосов
/ 25 июня 2010

Получите ли вы ошибку или нет после вызова closesocket в первый раз, зависит от того, что делает остальная часть вашего кода.

После того, как вы позвоните closesocket, этот идентификатор сокета свободен и может быть снова возвращен другим вызовом socket. Если вы снова наберете closesocket, вы закроете не исходный сокет, а вновь открытый

1 голос
/ 25 июня 2010

Они терпят неудачу.Попробуйте следующий фрагмент.

SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
closesocket(s);   // OK

shutdown(s, 2);   // fails
closesocket(s);   // fails
...