Сначала нужно различить две разные вещи:
- Выполнение операций с сокетом, некоторые из которых могут привести его в нерабочее состояние.
- Завершение ручки гнезда.
Вызов shutdown
с параметром 2 (который SD_BOTH
) равен (1). То есть вы сбрасываете весь ожидающий буфер, а также отбрасываете весь буфер приема. Так что вы не можете читать / писать больше. Однако вы все еще держите действительный дескриптор сокета. Вы все еще можете запросить / установить его параметры, если хотите. Например, можно позвонить по номеру getpeername
и узнать адрес, к которому вы подключены.
Кроме того, в зависимости от реализации, повторный вызов shutdown
не должен приводить к ошибке. Может быть, это имеет накопительный эффект.
С другой стороны, вызов closesocket
- это (2). Как только вы назвали это - вы ничего не можете сделать с этим дескриптором сокета. Теперь он недействителен.
Если у вашего сокета есть значение 1500 - оно останется, даже после вызова closesocket
. Потому что это просто переменная. Это все равно, что спросить, какое значение будет иметь указатель после delete
.
Однако это значение сокета (1500) больше недействительно. Вы не можете вызвать любую функцию сокета с этим значением.
Более того, если вы создадите еще один сокет - он, скорее всего, получит тот же номер. Здесь вы можете столкнуться с более серьезной проблемой - выполнять действия на другом сокете, не замечая этого.
В некоторых случаях рекомендуется присваивать значение INVALID_SOCKET
переменной сокета сразу после вызова closesocket
.
P.S.
Возможно, вызов shutdown
+ closesocket
не приведет к ошибке, потому что вы закрываете другой сокет.