Как связать привязку нового сервера, пока сервер активен - PullRequest
0 голосов
/ 19 марта 2020

Как я могу позволить ОС назначать доступные порты новым привязкам на сервере Indy, пока сервер активен?

  IdUDPServer.Active := True;

  for I := 0 to 4 do
  begin
    IdUDPServer.Bindings.add;
  end;

  for I := 0 to IdUDPServer.Bindings.Count-1 do
  begin
    WriteLn(IdUDPServer.Bindings[I].Port);
  end; 

Будет напечатано следующее:

40371
0
0
0
0
0

Я пробую это

var
  H : TIdSocketHandle; 
  ...
  for I := 0 to 4 do
  begin
    H := IdUDPServer.Bindings.add;
    try
      H.Bind;
    except
      On E: Exception do
        WriteLn(e.Message);
    end;
  end; 
  ...

Я получил следующее:

Socket Error # 9
Bad file number.
Socket Error # 9
Bad file number.
Socket Error # 9
Bad file number.
Socket Error # 9
Bad file number.
Socket Error # 9
Bad file number.
56554
0
0
0
0
0

Есть ли способ выполнить sh без деактивации и реактивности сервера?

, потому что я не не хочу терять ни одного активного клиента при добавлении новой привязки.

1 Ответ

0 голосов
/ 19 марта 2020

В настоящее время вы не можете добавить новые порты прослушивания к TIdUDPServer, пока он уже активен 1 . Он просто не предназначен для этого (по сравнению с TIdTCPServer). Порты прослушивания TIdUDPServer открываются, только когда его свойство Active переключено с False на True.

1: ну, вы можете вызывать Bindings.Add() сколько хотите, но новые привязки не будет иметь никакого эффекта в TIdUDPServer.

Когда вы вызываете Bindings.Add(), он присваивает DefaultPort сервера свойству Port нового объекта TIdSocketHandle. DefaultPort по умолчанию равно 0. Но чтобы действительно открыть TIdSocketHandle.Port для прослушивания пакетов, сначала необходимо деактивировать TIdUDPServer.

Вызов TIdSocketHandle.Bind() обновляет TIdSocketHandle.Port, если он доступен (таким образом, вы можете привязаться к порту 0 для назначения доступный эфемерный порт), но способ, которым вы используете Bind(), не работает, потому что вы не звоните заранее TIdSocketHandle.AllocateSocket(), поэтому TIdSocketHandle.Handle недопустим для использования Bind(). Но даже если вы заставите Bind() работать, это все равно не поможет, потому что TIdUDPServer создает отдельный поток слушателя для каждого объекта Binding только тогда, когда свойство Active переключено на True, поэтому любой новый TIdSocketHandle объектов, которые вы добавляете в Bindings, когда сервер уже активен, не будут считывать пакеты для передачи вашему OnUDPRead обработчику событий.

Итак, если вы хотите изменить порты Bindings в TIdUDPServer, вы должны сначала установить Active=False, затем изменить при необходимости, а затем установить Active=True. Я добавил запрос улучшения в систему отслеживания проблем Indy для вас:

# 294: Обновите TIdUDPServer, чтобы разрешить обновление привязок, пока он активен

Обратите внимание, что UDP не требует подключения, так что вы не «потеряете клиентов», как в TCP, если ваши UDP-клиенты не предназначены для остановки отправки пакетов на ваш сервер, если ОС сообщает о том, что его прослушивающий порт (-ы) закрыт как отправленный.

...