Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Адрес уже используется с помощью boost asio acceptor

Автор вопроса: AlexanderОтветов: 2

Я написал сервер, который прослушивает входящие TCP-соединения и подключающиеся к нему клиенты. Когда я выключаю сервер и перезапускаю его на том же порту, я иногда получаю сообщение об ошибке EADDRINUSE при вызове bind (...) (код ошибки: 98 в Linux). Это происходит, даже если я устанавливаю возможность повторного использования сокета.

Ошибка возникает не все время, но кажется, что это происходит чаще, когда клиенты подключены к серверу и отправляют данные, когда он завершает работу. Я предполагаю, что проблема в том, что все еще есть незавершенные соединения, пока сервер выключен (связанный раздел: https://stackoverflow.com/questions/41602/how-to-forcible-close-a-socket-in-time-wait).

На стороне сервера я использую boost :: asio :: ip :: tcp :: acceptor. Я инициализирую его опцией reuse_address (см. http://beta.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/basic_socket_acceptor.html). Вот фрагмент кода:

using boost::asio::ip::tcp;
acceptor acceptor::acceptor(io_service);
endpoint ep(ip::tcp::v4(), port);
acceptor.open(ep.protocol());
acceptor.set_option(acceptor::reuse_address(true));
acceptor.bind(ep);
acceptor.listen();

Акцептор закрывается:

acceptor.close();

Я также пробовал использовать acceptor.cancel () до этого, но он имел тот же эффект. Когда возникла эта ошибка, я не могу перезапустить сервер на том же порту в течение некоторого времени. Перезагрузка сети помогает, но не является постоянным решением.

Что мне не хватает?

Любая помощь будет принята с благодарностью! :)

  • ваш сервер разветвляет дочерние процессы? Sam Miller 16.11.2010
  • кроме того, вы уверены, что сокет находится в состоянии TIME_WAIT? Вы можете захотеть получить результат netstat -ap, когда это произойдет. Sam Miller 16.11.2010
  • Сэм, большое спасибо за ваш вклад! Это помогло мне найти решение моей проблемы. Оказалось, что я установил опцию повторного использования адреса для приемника, но не для всех других подключений. Еще раз большое спасибо за вашу помощь! Alexander 17.11.2010
  • Я добавил свои комментарии в качестве ответа. Sam Miller 17.11.2010
  • @Alexander Я знаю, что приду на вечеринку с опозданием на 11 лет, но не могли бы вы объяснить, что вы имели в виду, когда установили опцию повторного использования адреса для приемника, но не для всех других подключений? Что это за другие связи? Эти сокеты были перемещены из блока приемника для асинхронной обработки? user3224083 17.03.2021

c++socketsboostboost-asio

Ответы

Ответ 1 · рейтинг 1 · Sam Miller

Изначально это был комментарий к вопросу.


ваш сервер разветвляет дочерние процессы? Кроме того, вы уверены, что сокет находится в состоянии TIME_WAIT? Вы можете захотеть получить результат netstat -ap, когда это произойдет

Ответ 2 · рейтинг 1 · Hrissan

Когда решаешь эти проблемы "силой", кажется, ты бросаешь проблемы на голову?

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

Я бы не позволил включать это "решение" в сборку релизов в моей команде.

Помните, когда вероятность ошибки очень мала, тестирование чрезвычайно сложно!

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы