LINUX.ORG.RU

При повторном запуске сервера - bind: Address already in use


0

0

Написал элементарные сервер и клиент на C. Всё работает, но есть одна небольшая проблема. Если соединение первым завершает сервер, то при повторном его запуске bind выдаёт ошибку:
bind: Address already in use
И так примерно минуту при каждой попытке запуска сервера bind выдаёт такую ошибку. По истечении минуты, сервер запускается без ошибок и всё опять работает нормально.
Если соединение завершает клиент, то при повторном запуске сервера ошибок не возникает.

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

Ответ на: комментарий от defmacro

>Может вы некорректно закрываете соединение?

Может быть, хотя я в этом сомневаюсь.

Для демонстрации я написал очень простые версии клиента и сервера. Их можно скачать отсюда:
http://neo.xost.ru/temp/server.c
http://neo.xost.ru/temp/client.c
Скомпилировать их можно так:
gcc -o s server.c
gcc -o с client.c
Испльзуется порт 5555, клиент пытается соединиться к localhost. При запуске в качестве параметров передать время в секундах в течении которого будет поддерживаться соединение. Таким образом если запустить так:
./s 1
./c 2
И когда сервер закроет соединение опять попытаться запустить его:
./s 1
То он выдаст
bind: Address already in use

LinuxUser ★★★
() автор топика

а зачем сервер перезапускать вообще?

man accept

делается так:
0. открыли/завязали/etc сокет (socket, bind, listen)
1. получили входящее подключение (accept) и его файловый дескриптор
2. обработали (read, write)
3. закрыли файловый дескриптор соединения (close)
4. если не конец работы сервера, goto 1
5. закрыли сокет (close)

пункты 1-4 можно сделать (и обычно делают) многопоточными (а можно и гланды через select)

generatorglukoff ★★
()
Ответ на: комментарий от generatorglukoff

>а зачем сервер перезапускать вообще?

Это я понимаю. Дело не в том зачем перезапускать. Во-первых интересно почему так происходит. Во-вторых при отладке приходится минуту ждать. А в-третьих под виндой вроде такого нету...

LinuxUser ★★★
() автор топика
Ответ на: комментарий от generatorglukoff

>а зачем сервер перезапускать вообще?

Это я понимаю. Дело не в том зачем перезапускать. Во-первых интересно почему так происходит. Во-вторых при отладке приходится минуту ждать. А в-третьих под виндой вроде такого нету...

LinuxUser ★★★
() автор топика
Ответ на: комментарий от LinuxUser

close на сервере вижу, а где вызов shutdown(sock, SHUT_RDWR) и shutdown(listner, SHUT_RDWR) ?
у клиента тоже нет shutdown()

вообще - даже не смотря на то что ты добавишь shutdown, может так случится
что сокет ещё TIME_WAIT а сервер уже перезапускается. сокет в состоянии TIME_WAIT считается занятым.
Добавь на сервере после socket перед bind 
    int opt = 1;
    if (setsockopt (listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) == -1) perror("setsockopt");

Eshkin_kot ★★
()
Ответ на: комментарий от Eshkin_kot

Добавил вызов setsockopt, теперь задержки нету. Спасибо! Пойду изучать что делает setsockopt :)

Кстати, разве обязательно вызывать shutdown?

Я изучал сокеты по статье http://www.rsdn.ru/article/unix/sockets.xml

Там ничего про обязательный вызов shutdown не написано.

LinuxUser ★★★
() автор топика
Ответ на: комментарий от asgard

Благодарю. Прочитал, осознал ширину и глубину проблемы, а также методы её решения :) . Я кстати гуглил, но видать на русском только, потому как такую замечательную статью не нашёл.

LinuxUser ★★★
() автор топика
Ответ на: комментарий от LinuxUser

Про reuseaddr в каждой книжке по сетевому программированию говорится.

mv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.