How i can let the OS assign available ports to new bindings in Indy server while the server is active ?
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;
Will print the following :
40371
0
0
0
0
0
I try this
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;
...
I got the following:
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
Is there any way to accomplish this without deactivate and reactive the server ?
because i don't want to lose any active client while adding new binding.
At this time, you can't add new listening ports to TIdUDPServer
while it is already active 1. It is simply not designed to allow that (compared to TIdTCPServer
, which is). TIdUDPServer
's listening ports are opened only when its Active
property is toggled from False to True.
1: well, you can call Bindings.Add()
all you want, but the new bindings won't have any effect in TIdUDPServer
.
When you call Bindings.Add()
, it assigns the server's DefaultPort
to the Port
property of the new TIdSocketHandle
object. The DefaultPort
is 0 by default. But to actually open the TIdSocketHandle.Port
to listen for packets requires TIdUDPServer
to be deactivated first.
Calling TIdSocketHandle.Bind()
updates the TIdSocketHandle.Port
if accessful (thus allowing you to bind to port 0 to assign an available ephemeral port), but the way you are using Bind()
does not work because you are not calling TIdSocketHandle.AllocateSocket()
beforehand, so the TIdSocketHandle.Handle
is not valid for Bind()
to use. But even if you did get Bind()
to work, it still would not help you, because TIdUDPServer
creates a separate listener thread for each Binding
object only when the Active
property is toggled to True, so any new TIdSocketHandle
objects you add to the Bindings
while the server is already active will not read packets to give to your OnUDPRead
event handler.
So, if you want to modify the Bindings
ports in TIdUDPServer
, you must set Active=False
first, then modify as needed, and then set Active=True
. I have added an enhancement request to Indy's issue tracker for you:
#294: Update TIdUDPServer to allow updating Bindings while active
Note that UDP is connection-less, so you won't "lose clients" like in TCP, unless your UDP clients are designed to stop sending packets to your server if its listening port(s) are reported by the OS as closed when the packets are sent.