I would like to read data from an electronic device that sends data to my PC by UDP. I have programmed a UDP server in Delphi. An exception occurs in class EIdSocketError (Failure #10049). Here is my code:
procedure TForm1.Button1Click(Sender: TObject);
begin
IdUDPServer1.Bindings.add.IP := '192.168.1.1'; //Electronic device ip
IdUDPServer1.Bindings.add.Port:= 49152; //Electronic device port
IdUDPServer1.OnUDPRead:= UDPRead;
IdUDPServer1.Active:=True;
end;
procedure TForm1.UDPRead (Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
bytes_received: integer;
begin
bytes_received:=AData.size;
end;
What am I doing wrong?
Thanks in advance
As Keith Miller stated, you are misusing the Bindings
property. You are adding 2 bindings to the server - one for 192.168.1.1
on port 0
and another for 0.0.0.0
on port 49152
. You need to call Bindings.Add()
only once for each IP/Port pair you want to bind to, eg:
var
Binding: TIdSocketHandle
Binding := IdUDPServer1.Bindings.Add;
Binding.IP := ...;
Binding.Port := ...;
Or:
with IdUDPServer1.Bindings.Add do
begin
IP := ...;
Port := ...;
end;
If you set the DefaultPort
property ahead of time, then you can simplify the above to this:
IdUDPServer1.DefaultPort := ...;
IdUDPServer1.Bindings.Add.IP := ...;
With that said, socket error 10049 is WSAEADDRNOTAVAIL
, which means you are using the wrong IP address in the first place. You need to specify an IP that belongs to the PC that TIdUDPServer
is running on - the IP that the device will be sending UDP packets to. You can either bind to the single wildcard IP 0.0.0.0
(or just a blank string ''), which tells TIdUDPServer
to bind to all available local IPs:
IdUDPServer1.DefaultPort := ...;
IdUDPServer1.Bindings.Add.IP := ''; // or: '0.0.0.0'
Or you can use Indy's GStack.LocalAddresses
property to determine the locally available IPs and create separate Bindings
for them individually as needed.
IdUDPServer1.Bindings.Clear;
IdUDPServer1.DefaultPort := ...;
with GStack.LocalAddresses do
begin
for I := 0 to Count-1 do
IdUDPServer1.Bindings.Add.IP := Strings[I];
end;
Update: if you bind the server to port 0 to let the OS pick a port, you can discover what port was selected by looking at the TIdSocketHandle.Port
property after the server was activated:
var
Binding: TIdSocketHandle
ListeningPort: TIdPort;
IdUDPServer1.Bindings.Clear;
Binding := IdUDPServer1.Bindings.Add;
Binding.IP := ...;
Binding.Port := 0;
{
or:
IdUDPServer1.DefaultPort := 0;
Binding := IdUDPServer1.Bindings.Add;
Binding.IP := ...;
}
IdUDPServer1.Active := True;
ListeningPort := Binding.Port;