Сокет в C: правильный способ закрыть сокет - PullRequest
0 голосов
/ 10 ноября 2018

Я часто вижу примеры кодов для серверной программы, использующей сокет.

(для простоты здесь я не проверяю возвращаемые значения функций, таких как socket () или bind () и т. Д.)

int sockfd = 0, newsockfd = 0;
struct sockaddr_in address;

sockfd = socket(AF_INET, SOCK_STREAM, 0);

bind(sockfd, (struct sockaddr*)&address, sizeof(address));
listen(sockfd, 1);

newsockfd = accept(sockfd, (struct sockaddr*)NULL, NULL);

... do some communication ...

close(newsockfd);

Большинство примеров кодов, которые я нашел в Интернете, имеют close (newsockfd) , но не имеют close (sockfd) .Мой вопрос: действительно ли правильно НЕ закрывать sockfd .

Если это правильно, я хочу знать почему.Насколько я понимаю, sockfd является одним из дескрипторов файлов, и, похоже, у него нет причин выходить из программы, не закрывая его.

В частности, мне интересно, что not-closed-sockfd может вызвать ошибку связывания (например, этот сокет уже используется ...) когда программа будет работать в следующий раз.

Я очень признателен, если вы мне поможете.Спасибо за ваше время.

Ответы [ 3 ]

0 голосов
/ 10 ноября 2018

Вы должны всегда закрывать sockfd, когда прекращаете прослушивание.

Две причины, по которым некоторые разработчики не очень заботятся о том, чтобы не закрывать sockfd:

  • Если ваша программа завершает работу, не закрывая ее, ОС закроет для вас sockfd
  • В большинстве случаев серверы постоянно поддерживают прослушивание (например, в течение месяцев)

Однако, если ваша программа запускает прослушивающий сокет для какого-либо события, затем закрывает его через некоторое время и делает цикл, тогда вы должны закрыть sockfd, чтобы предотвратить ошибку EADDRINUSE (адрес уже используется) на следующей итерации, и память течь.

Кроме того, ошибка EADDRINUSE (адрес уже используется) может возникать при других обстоятельствах, которые я здесь не описываю.

0 голосов
/ 10 ноября 2018

sockfd действует как серверный сокет: он используется только для приема все большего и большего количества входящих соединений. Вы сохраняете sockfd открытым, связанным и прослушивающим, пока вы должны принимать и обрабатывать новые соединения на newsockfd, которые удерживают текущее соединение, на котором вы читаете / пишете из / в какую-либо одноранговую программу. Когда вы закончите с newsockfd, вы закроете его и, если потребуется, примете новый с помощью accept () на sockfd. И так далее.

0 голосов
/ 10 ноября 2018

Ресурсы, выделенные приложением, такие как дескрипторы памяти или открытых файлов (которые включают в себя сокеты), будут автоматически освобождены современной ОС при выходе из программы. Таким образом, если серверный сокет должен быть доступен во всей программе (для приема соединений), хорошо не явно закрывать его, а позволить ОС делать это при выходе из приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...