Vaclav_ Ответов: 4

Повторное использование адреса в сокете - как это на самом деле работает ?


Я все еще не уверен, что делаю это правильно, особенно в правильной последовательности
и со всеми правильными вариантами.

Я понимаю, что "сокет" может быть опцией, позволяющей "привязать" повторно использовать порт или адрес.
Но это не так.
Когда я пытаюсь получить доступ к тому же адресу во второй раз , не закрывая сокет, я ожидаю, что эти параметры позволят "привязать" повторно использовать адрес.( на человека Linux)

Но "привязка" всегда будет завершаться ошибкой "адрес уже используется".

Это не то, что я ожидаю, когда сокет настроен на повторное использование адреса.

Пожалуйста, поймите, что это так. в частности, спрашивая, почему "повторное использование адреса" не работает как и ожидалось.

Может быть, я упускаю какой-то вариант?

У меня нет других вопросов для обсуждения.

Что я уже пробовал:

Here is the code sequence I am using 


FileDescriptor_socket = socket(AF_INET, SOCK_STREAM, 0); //BTPROTO_RFCOMM);
setsockopt(FileDescriptor_socket, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR | SO_DEBUG), (char*) &option,sizeof(option));
bind(...

Richard MacCutchan

Введите команду "netstat-a" в окне cmd, и вы увидите, находится ли ваш порт все еще в режиме прослушивания. Если вы не закроете свою розетку должным образом, то она будет оставаться в использовании до тех пор, пока не истечет время ожидания. Тайм-аут TCP обычно составлял 15 минут, не уверен, что он все еще тот же.

4 Ответов

Рейтинг:
1

Richard MacCutchan

Цитата:
SO_REUSEADDR
Указывает, что правила, используемые при проверке предоставленных адресов
в вызове bind(2) должно быть разрешено повторное использование локальных адресов. Для
AF_INET сокеты это означает, что сокет может связываться, за исключением тех случаев, когда
существует активный прослушивающий сокет, привязанный к этому адресу.

Когда прослушивающий сокет привязан к INADDR_ANY с помощью spe‐
порт-рам, то это не возможно, чтобы привязать к этому порту для
любой местный адрес. Аргумент-это целочисленный логический флаг.

Итак, с каким адресом он был связан до этого звонка, и с каким адресом вы пытаетесь связать его сейчас?


Рейтинг:
1

Vaclav_

Thank you very much for the reference. 
That is EXACTLY what is NOT working. 
I do get past bind after first call, when "bind" succeeds. 
It is the next call, after the app is restarted, which fails to reuse the address.
I'll try to access socket etc. using TCP , maybe the bluetooth application is the problem. 

PS I keep getting this "servers are overworked" message after I submit comment.


Richard MacCutchan

Пожалуйста, не публикуйте комментарии в качестве решений; используйте Ответить кнопка над соответствующим комментарием или У вас есть вопрос или комментарий? кнопка под соответствующим решением. В противном случае ваши комментарии, скорее всего, будут пропущены.

А сообщение "серверы перегружены работой" просто означает, что в CodeProject central многое происходит. Со временем все прояснится.

Рейтинг:
0

k5054

Там есть куча примеров, на которых вы можете погуглить, но в основном последовательность такова

int sfd = socket(/*...*/);
setcokopts( /*...*/);
bind( /*...*/);  /* At this point you have an open socet waiting for connections.*/
                 /* You can then listen on the socket for a new connection e.g. */

If you carefully read the post , the above sequence WORKS  just fine, that is NOT the issue. I do not see how setsockopt and its options allows for address reuse. That IS the  issue. 

I realize that I am NOT properly closing the the socket when I exit() the project during development.  
The issue is when I rerun the project / application again the address remains in use. Irregardless of reason it remains in use - the setsockopt specifically have option to reuse the address - just for bind to reuse it. 
And it does not. bind returns an  error  the "address already in use"  and any further processing is useless. 

Yes, I can try closing the socket, but that would defeat  "address reuse " option.

    
listen(sfd, backlog); /* backlog is the queue length of connections waiting */

for( ;; ) {
   int connection = accept(sfd, /* ... *);
   /* work with connection */
   close(connection);
}

Тебе не нужно звонить bind() более одного раза на открытую розетку (sfd). В общем, так и будет fork() или запустите новый поток для обработки нового connection, так что вы можете обработать backlog быстро.


k5054

Пожалуйста, не редактируйте ответы других людей своими собственными комментариями. Это затрудняет комментирование и граничит с грубостью.

Пожалуйста, взгляните наэтот[^] код. Это работает так, как и следовало ожидать:

07:19:42 $ ./tcp-echo 9999
Server is listening on 9999
^C
07:19:45 $ ./tcp-echo 9999
Server is listening on 9999
^C
07:19:47 $ ./tcp-echo 9999
Server is listening on 9999
^C
07:19:49 $ ./tcp-echo 9999
Server is listening on 9999
^C
07:19:50 $ 

как вы можете видеть, это работает, как и ожидалось. Даже если я ... kill -9 сервер, следующий вызов работает.
Я даже попробовал это сделать, привязав к определенному адресу с помощью inet_aton() без каких-либо изменений в поведении.
Сравните это с тем, что вы делаете, и посмотрите, дает ли это ключ к пониманию того, что вы делаете неправильно. Если это не работает, то что-то держит порт открытым между вызовами. Взгляните на что sudo netstat -tlnp должен тебе сказать.

Рейтинг:
0

k5054

Для окончательное решение информация о SO_REUSEADDR, вы должны получить копию W. Richard Stevens "UNIX Network Programming". Вот соответствующие страницы из google books: Сетевое программирование UNIX: The sockets networking API - W. Richard Stevens, Bill Fenner, Andrew M. Rudoff - Google Books[^]