сбой bind () с SO_REUSEADDR - PullRequest
       13

сбой bind () с SO_REUSEADDR

6 голосов
/ 30 ноября 2011

Моя задача - реализовать игру для двух игроков между двумя компьютерами, подключенными через TCP. Одним из требований является то, что только победителю предоставляется право выбора игры снова или нет. Если сервер выигрывает и решает не играть дальше, клиент должен перезапуститься как сервер и принять новые подключения.

Мой подход: Если игра LOST (в режиме клиента), закройте sockfd и создайте новую. Затем используйте setsockopt, чтобы разрешить повторное связывание с использованием SO_REUSEADDR, а затем вызвать bind.

int yes = 1;
if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 )
{
    perror("setsockopt");
}

if ( bind(sockfd, (struct sockaddr*)&svr, sizeof(svr) ) == -1 )
{
    perror("server: bind");
}

Но все равно я получаю ту же ошибку "Адрес уже используется". Я пробовал спать в течение 150 секунд, прежде чем воссоздать сокет, и этот метод работает.

ПРИМЕЧАНИЕ: я тестирую это на том же ПК. Он может работать на двух связанных компьютерах, но необходимо, чтобы он работал на одном компьютере. Пожалуйста, помогите.

Ответы [ 3 ]

2 голосов
/ 01 декабря 2011

Поскольку вы работаете с этой же системой, похоже, что у вас есть состояние гонки. Клиент пытается bind() сокет непосредственно перед тем, как сервер закрыл его (при условии, что и сервер, и клиент устанавливают SO_REUSEADDR на своих сокетах).

Вам необходимо реализовать какое-то рукопожатие, которое позволяет серверу информировать клиента после того, как он закрыл сокет прослушивания - возможно, сервер должен закрыть сокет прослушивания, прежде чем он закроет активный сокет из последней игры?

1 голос
/ 30 ноября 2011

SO_REUSEADDR позволяет одновременно привязывать более конкретный адрес , то есть первый сервер прослушивает INADDR_ANY (все интерфейсы), а последующие серверы прослушивают различные конкретные адреса интерфейса.

Второй сценарий - когда прослушивающий сокет TCP принимает соединение, которое сохраняется в использовании, но сам прослушивающий сокет закрывается, а затем снова открывается - скажем, процесс родительского сервера завершается и запускается снова.

В обоихв случаях, когда вам нужно всегда установить SO_REUSEADDR опцию на сокете прослушивания, прежде чем звонить bind(2).

0 голосов
/ 04 сентября 2014

Установка этой опции сокета позволяет повторное использование локального адреса. Если возникает проблема при попытке привязки к порту, который был закрыт, но не освобожден (может занять до 2 минут, как определено TIME_WAIT). Примените параметр сокета SO_REUSEADDR, чтобы немедленно освободить ресурс и обойти состояние TIME_WAIT. 0 = отключить, 1 = включить.

Позволяет другим сокетам связывать () с этим портом, если к этому порту уже не подключен активный прослушивающий сокет. Это позволяет обойти эти сообщения об ошибках «Адрес уже используется» при попытке перезагрузить сервер после сбоя

...