Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как уменьшить количество разрешенных подключений к серверу до одного?  (Прочитано 31354 раз)
0 Пользователей и 1 Гость смотрят эту тему.
demon051
Помогающий

ru
Offline Offline

« : 07-12-2018 10:10 » 

Всем привет.

Вопрос в общем-то идиотский ) Все борются с тем, как увеличить, а мне надо наоборот

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

Код:
.....
while(...)
{
if(select(FD_SETSIZE, &readset, NULL, NULL, &connection_timeout)==0)
continue;
//обработка подключения
.....
while(...)
{//обмен
....
}
.....
}


но если другой клиент попробует подключиться к этому же серверу, то он на своей стороне получит ОК.
однако, поскольку на сервере select не обработает это подключение, то клиент останется в подвешенном состоянии.

Вопрос: можно ли как-то указать, что если уже есть подключение, то все другие попытки получают отказ?

Понятно, что код можно переписать так, чтобы всё это фильтровать... Но он уже написан как есть и переделывать очень не хочется за "тем парнем". Надо "косячить" дальше  Улыбаюсь
Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 07-12-2018 10:32 » 

Функция listen принимает вторым аргументом длину очереди на ожидание соединения - если поставить 1, то всем, кто не успел первым встать в очередь, должен следовать отказ в подключении, пока очередь не разгребут. Так подойдёт?
Не нашёл, что точно происходит, если длину очереди выставить в 0 - надо глубже покопать, но мануалы установку такого значения допускают.
« Последнее редактирование: 07-12-2018 10:42 от Вад » Записан
demon051
Помогающий

ru
Offline Offline

« Ответ #2 : 07-12-2018 10:51 » 

Функция listen принимает вторым аргументом длину очереди на ожидание соединения - если поставить 1, то всем, кто не успел первым встать в очередь, должен следовать отказ в подключении, пока очередь не разгребут. Так подойдёт?
Не нашёл, что точно происходит, если длину очереди выставить в 0 - надо глубже покопать, но мануалы установку такого значения допускают.
в listen уже стоит 1.
остается пробовать 0 Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 07-12-2018 10:57 » 

demon051, Вад, когда я в своё время ковырялся с данным вопросом, обнаружил, что длина очереди N, указанная в listen - это возможность одновременного подключения сразу N сокетов, это не ограничение на общее количество подключений. То есть, даже при значении "1" слушалка всё равно будет принимать запросы на подключение (в виндовом просмотрщике портов висит LISTENING сокет)

решение: при достижении N подключений нужно отключать слушающий сокет. Как только хотя бы одно соединение отпало, слушалку запускаем.

Если по каким-то причинам не хочется прибивать слушалку, то нужно делать Accept для "лишних" входящих, а затем их тут же Close
Записан

demon051
Помогающий

ru
Offline Offline

« Ответ #4 : 07-12-2018 11:06 » 

demon051, Вад, когда я в своё время ковырялся с данным вопросом, обнаружил, что длина очереди N, указанная в listen - это возможность одновременного подключения сразу N сокетов, это не ограничение на общее количество подключений. То есть, даже при значении "1" слушалка всё равно будет принимать запросы на подключение (в виндовом просмотрщике портов висит LISTENING сокет)

решение: при достижении N подключений нужно отключать слушающий сокет. Как только хотя бы одно соединение отпало, слушалку запускаем.

Если по каким-то причинам не хочется прибивать слушалку, то нужно делать Accept для "лишних" входящих, а затем их тут же Close


Прикрутил я вот какой костыль...

значит сначала делаем listen(listener, 1)
затем в select ждем подключения. потом accept и так далее.
а когда установили связь по сокету, вызываем listen(listener, 0) !!!!

всё. дальнейшие попытки подключения невозможны. правда настолько невозможны, что подключающийся следующий клиент впадает в ступор. ну видимо до таймаута соответствующего.
но в общем, это дело клиента, просечь, что почему-то он не может подключиться... на то он и костыль, чтобы не всё так просто было Улыбаюсь
надо только корректно отрабатывать отключение первого клиента, после чего снова вызывать listen(listener, 1)

Погонял немного. Вроде работает. Но, посмотрим, как к этому отнесется критически настроенная братва Улыбаюсь Т.е. эксплуататоры Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 07-12-2018 11:36 » 

demon051, чтобы он не впадал в ступор, я выше описал два варианта действий:
1) убивать слушающий сокет (то есть, прямо прибивать хендл) при достижении N соединений. И создавать обратно, когда разрешены новые соединения
2) обязательно делать accept и close лишних входящих
Записан

demon051
Помогающий

ru
Offline Offline

« Ответ #6 : 07-12-2018 11:37 » 

demon051, чтобы он не впадал в ступор, я выше описал два варианта действий:
1) убивать слушающий сокет (то есть, прямо прибивать хендл) при достижении N соединений. И создавать обратно, когда разрешены новые соединения
2) обязательно делать accept и close лишних входящих

да не, всё ок. проверил - таймаут по крайней мере у меня на компе - 10-15 сек.
отдам на проверку тому кто клиента ковыряет. как у него это будет выглядеть. скорее всего по таймауту будет ошибка вылезать.


PS - убивать листнера и назначать ему кол-во возможных подключений = 0 - разве не одно и то же по факту? за исключением того, что при убийстве нужно будет его пересоздавать заново...
« Последнее редактирование: 07-12-2018 11:46 от demon051 » Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 07-12-2018 20:01 » 

Вот любитель сложностей! Леха уже сказал: после возврата из accept (он вернет сокет подключения) сделать close на слушающий сокет. Никаких таймаутов у других клиентов не будет, если конечно у тебя не глухой файрвол с дропом всех ненужных пакетов.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 08-12-2018 05:09 » new

но только close нужно  подключенный (accepted) сокет, а не слушающий

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

Close слушающего сокета - это для варианта, когда слушалка прибивается (там ни о каких accept речи уже не пойдёт). Да, нужно будет пересоздавать заново, зато не будет лишнего напряга для системы (теоретически, отпинывание accept-close можно "заддосить", а вот с прибитой слушалкой такого не провернёшь)

Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines