Ошибка: адрес уже используется во время привязки к сокету с адресом, но номер порта отображается бесплатно с помощью `netstat`
Я попытался связать свой сокет (сокет сервера) с номером порта 8000
. Он работал и выполнял эту работу для меня. В конце кода я также закрываю сокет. В следующий же миг я снова запустил свой код, и он показывает мне, что адрес уже используется. Я напечатал значение значений ошибок strerror(errno);
, чтобы проверить, правильно ли работает мой код в каждой точке. Чтобы проверить, свободен ли порт, я проверил его с помощью netstat
, но он показывает, что номер порта 8000
свободен. Это случалось со мной много раз. Каждый раз я жду еще несколько секунд, а затем снова начинает работать. Я использую язык c. Итак, какова причина этого поведения моей ОС.
После нескольких секунд я запускаю код, а затем он работает.
[email protected]:~/Desktop/testing$ sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
[email protected]:~/Desktop/testing$ sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1348/lighttpd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 984/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1131/cupsd
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1211/mysqld
tcp6 0 0 :::22 :::* LISTEN 984/sshd
tcp6 0 0 ::1:631 :::* LISTEN 1131/cupsd
[email protected]:~/Desktop/testing$ sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
[email protected]:~/Desktop/testing$
Ответы
Ответ 1
Я столкнулся с этой проблемой. Это связано с тем, что вы закрываете соединение с сокетом, но не с самим сокетом. Сокет может войти в состояние TIME_WAIT (чтобы гарантировать, что все данные были переданы, TCP гарантирует доставку, если это возможно) и займет до 4 минут для выпуска.
или, для ДЕЙСТВИТЕЛЬНО подробного/технического объяснения, проверить эту ссылку
Это может быть очень неприятно, но нет никакого реального пути вокруг него, и это не ошибка.
Ответ 2
Попробуйте netstat следующим образом: netstat -ntp
, без -l
. Он покажет tcp-соединение в
TIME_WAIT
.
Ответ 3
Я знаю, что прошло некоторое время, так как вопрос был задан, но я смог найти решение:
int sockfd;
int option = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
Это позволяет сразу же использовать сокет.
Прошу прощения, если это неверно. Я не очень опытен с сокетами
Ответ 4
Просто введите
unlink [SOCKET NAME]
в терминале, тогда ошибка больше не должна существовать.
Ответ 5
Как уже говорилось, ваш сокет, вероятно, входит в состояние TIME_WAIT
. Эта проблема хорошо описана Томасом А. Прекрасным здесь.
В сводке процесс закрытия сокетов приведен ниже:
![Socket closing process]()
Томас говорит:
Взглянув на диаграмму выше, ясно, что TIME_WAIT
может быть избегают, если удаленный конец инициирует замыкание. Таким образом, сервер может избегайте проблем, позволяя клиенту закрыться первым. Приложение протокол должен быть сконструирован таким образом, чтобы клиент знал, когда его закрыть. сервер может безопасно закрываться в ответ на EOF от клиента, однако ему также необходимо установить тайм-аут, когда он ожидает EOF в случае клиент покинул сеть бесцеремонно. Во многих случаях просто ожидая несколько секунд до закрытия сервера, будет достаточно.
Использование SO_REUSEADDR
обычно предлагается в Интернете, но Томас добавляет:
Как ни странно, использование SO_REUSEADDR
может привести к более сложному "адресу уже используемые". SO_REUSADDR
позволяет использовать порт, который застрял в TIME_WAIT
, но вы все еще не можете использовать этот порт для установки подключение к последнему месту, к которому оно подключилось. Какие? Предположим, что я выбираю локальный порт 1010 и подключиться к порту foobar.com 300, а затем закрыть локально, оставив этот порт в TIME_WAIT
. Я могу повторно использовать локальный порт 1010 сразу для подключения к любому месту, кроме порта foobar.com
300.
Ответ 6
Даже icfantv ответ на этот вопрос уже совершенен, у меня все еще есть больше результатов в моем тесте.
Как серверный сокет в состоянии прослушивания, если он только в состоянии прослушивания, и даже он принимает запрос и получает данные со стороны клиента, но без каких-либо действий по передаче данных. Мы все равно можем перезапустить сервер сразу после его остановки. Но если на стороне сервера будет выполняться какое-либо действие передачи данных клиенту, тот же перезапуск службы (тот же самый порт) будет иметь эту ошибку: (адрес уже используется).
Я думаю, что это вызвано принципами проектирования TCP/IP. Когда сервер отправляет данные обратно клиенту, он должен обеспечить успешную передачу данных, для этого OS (Linux) должен контролировать соединение, даже серверное приложение закрыло этот сокет.
Но я все же считаю, что разработчик сокета ядра может улучшить эту проблему.
Ответ 7
полученная ошибка:
cockpit.socket: Failed to listen on sockets: Address already in use
обнаруженное исправление:
- Мне пришлось отключить selinux
-
в службе /usr/lib/systemd/system/cockpit я изменил
line:
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws --selinux-type=etc_t
в
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws
так что вы можете видеть, что я вывел аргумент о selinux
то я побежал:
systemctl daemon-reload
systemctl start cockpit.service
то я просмотрел:
Я принял самоподписанный сертификат и был
чтобы успешно войти в кабину и использовать ее в обычном режиме.
Это все на машине fedora25. порт 9090 уже
добавлен с помощью firewall-cmd
Ответ 8
Для AF_UNIX вы можете использовать функцию разблокировки вызова (путь); после подключения close() в приложении "server"