Ошибка связи при воссоздании сокета
A имеют следующий сокет-слушатель:
int sd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(http_port);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sd,(sockaddr*)&addr,sizeof(addr))!=0)
{
...
}
if (listen(sd, 16)!=0)
{
...
}
int sent = 0;
for(;;) {
int client = accept(sd, (sockaddr*)&addr, (socklen_t*)&size);
if (client > 0)
{
...
close(client);
}
}
Если использование
close(sd);
а затем пытается воссоздать сокет с тем же кодом, произошла ошибка привязки, и только через 30-60 секунд новый сокет будет создан успешно.
Есть ли способ создать или закрыть каким-нибудь классным способом, чтобы избежать ошибки связывания?
Ответы
Ответ 1
Где-то в ядре все еще есть информация о вашем предыдущем сокете. Скажите ядру, что вы все равно захотите повторно использовать порт:
int yes=1;
//char yes='1'; // use this under Solaris
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
perror("setsockopt");
exit(1);
}
Для более подробного объяснения см. раздел bind() в beej Guide to Network Programming.
Ответ 2
Это ожидаемое поведение для сокетов TCP. Когда вы закрываете сокет, он переходит в состояние TIME_WAIT. Он будет принимать и удалять пакеты для этого порта. Вам нужно сразу установить параметр SO_REUSEADDR
.
Ответ 3
Вы не должны закрывать связанный сокет, а затем пытаться его воссоздать.
accept
возвращает вновь созданный сокет только для этого соединения, он должен быть закрыт. т.е.: вы должны делать -
close(client);
Ответ 4
Попробуйте позвонить setsockopt
с помощью SO_REUSEADDR
. См. http://msdn.microsoft.com/en-us/library/ms740476(v=vs.85).aspx