Recently I made some very small, very light app that uses two UDP client and two UDP Server components. Apart from several functions, it has basically nothing else in it. I was stuck for a while with "Cannot bind socket. Address and port already in use", but somehow solved that with changing the ports, using rsTrue property on Reuse Socket, but somehow, several users still got that error when they try to run the connection from the app.
The server and client has to use same port and same address, as the UDPClient needs to have BoundPort the same as UDPServer's binding port. That's because the responses are being sent to the same port the request came from. This was causing the primary error, which was solved with rsTrue property.
Now I wonder, is there any chance that system overrides this settings by something, I'm not familiar with? Because on 12 computers I have tested so far, it worked fine (on one I had to kill Bonjour service as it was using the exact port that I needed, but other than that...)
What could be causing errors otherwise?
These are settings which are being called on Connect button click:
Server.Binding.IP:=Interface.Text;
Server.Binding.Port:=StrToInt(Port.Text);
Server.DefaultPort:=StrToInt(Port.Text);
Client.Host:= DeviceIP.Text;
Client.Port:= 10023;
Client.BoundIP:= Interface.Text;
Client.BoundPort:= StrToInt(Port.Text);
LocalServer.Binding.IP:= '127.0.0.5';
LocalServer.Binding.Port:= 10023;
LocalServer.DefaultPort:= 10023;
LocalClient.BoundIP:= '127.0.0.1';
LocalClient.BoundPort:= 10024;
LocalClient.Host:= '127.0.0.1';
LocalClient.Port:= 10023;
try Client.Active:=True; finally end;
try Server.Active:=True; finally end;
try LocalClient.Active:=True; finally end;
try LocalServer.Active:=True; finally end;
Where Port is the TEdit field for user to enter port, DeviceIP the device's IP, and Interface the local network interface IP that he will use.
The only hardcoded thing that doesn't really need to be hardcoded is LocalClient.BoundPort:=10024, it's just to make GUI as light as possible. But changing this doesn't help either.
The app is kind of a proxy server between the original App on PC, and the device on network.
The 10023 must be set as is, since the device only listens on that port, and the original app only sends to that port!
Any help would be appreciated.
You do not need to use separate TIdUDPClient
and TIdUDPServer
on the same port. You can use TIdUDPServer
by itself and let it handle both sending and receiving. No need to use a separate TIdUDPClient
at all.
Also, you are not using the Binding
property correctly. When you read a server's Binding
property for the first time, the socket is bound using the settings from the server's Bindings
collection. Your assignments to Binding.IP
and Binding.Port
are then ignored. You need to configure the server's Bindings
collection first, then use the server's Binding
property only for sending (the server will handle the reading for you).
Try this:
Server.Active := False;
Server.Bindings.Clear;
Server.DefaultPort := StrToInt(Port.Text);
Server.Bindings.Add.IP := Interface.Text;
Server.Active := True;
...
Server.Binding.Send(DeviceIP.Text, 10023, data here);
Replies will arrive in the server's OnUDPRead
event.
BTW, since you are writing a proxy, have a look at the TIdMappedPortUDP
component.