Delphi Delphy Indy10-TIdUDPClient-获取我接收数据包的IP

Delphi Delphy Indy10-TIdUDPClient-获取我接收数据包的IP,delphi,Delphi,我创建了一个TIdUDPClient,如下所示: myUDPClient := TIdUDPClient.Create(nil); myUDPClient.ReceiveTimeout := 500; myUDPClient.Binding.Port := 300; myUDPClient.Active := True; 没有指定绑定IP,因为我有3个带动态寻址的以太网适配器(192.168.x.x、10.10.x.x和172.16.x.x),所以绑定IP是由Indy生成的,它是0.0.0。

我创建了一个TIdUDPClient,如下所示:

myUDPClient := TIdUDPClient.Create(nil);
myUDPClient.ReceiveTimeout := 500;
myUDPClient.Binding.Port := 300;
myUDPClient.Active := True;
没有指定绑定IP,因为我有3个带动态寻址的以太网适配器(192.168.x.x、10.10.x.x和172.16.x.x),所以绑定IP是由Indy生成的,它是
0.0.0
。 当我收到数据包时,我可以确定发送方IP,但我无法确定接收数据包的本地IP(不是0.0.0.0,而是分配给我的计算机的3个IP之一)


你知道实现这一目标的方法吗

不要直接分配给
Binding.Port
,而是分配给
myUDPClient.BoundPort
,让
TIdUDPClient
内部分配给
Binding.Port

由于您在本地绑定到
0.0.0.0
,因此在使用
TIdUDPClient
读取数据包时无法确定目标IP,因为它使用套接字API
recvfrom()
函数,该函数不报告该信息。socketapi
getsockname()
函数将报告
0.0.0.0
,因为这才是socket真正绑定的对象

在Windows XP+上,您可以使用
GStack.ReceiveMsg()
来接收数据包。它有一个
TIdPacketInfo
输出参数,其中包含一个
DestIP
字段(您必须使用
Binding.SetSockOpt()
来启用
ReceiveMsg()
来收集该信息),例如:

或者,您可以切换到
TIdUDPServer
,并在其
Bindings
集合中为要在其上接收数据包的每个本地IP创建一个单独的条目:

myUDPServer := TIdUDPServer.Create(nil);
myUDPServer.DefaultPort := 300;
myUDPServer.OnUDPRead := UDPRead;

LocalIPs := TStringList.Create;
try
  GStack.AddLocalAddressesToList(LocalIPs);
  for I := 0 to LocalIPs.Count-1 do
    myUDPServer.Bindings.Add.IP := LocalIPs[I];
finally
  LocalIPs.Free;
end;
{
Or this, if you are using an up-to-date Indy 10 snapshot:

LocalIPs := TIdStackLocalAddressList.Create;
try
  GStack.GetLocalAddressList(LocalIPs);
  for I := 0 to LocalIPs.Count-1 do
    myUDPServer.Bindings.Add.SetBinding(LocalIPs[I].IPAddress, myUDPServer.DefaultPort, LocalIPs[I].IPVersion);
finally
  LocalIPs.Free;
end;
}

myUDPServer.Active := True;

var
  Buffer: TIdBytes;
  BufLen: LongWord;
  PktInfo: TIdPacketInfo;
begin
  SetLength(Buffer, ...);
  BufLen := GStack.ReceiveMsg(myUDPClient.Binding.Handle, Buffer, PktInfo);
  // use Buffer up to BufLen bytes
  // PktInfo.DestIP will be the IP that received the packet
end;
myUDPServer := TIdUDPServer.Create(nil);
myUDPServer.DefaultPort := 300;
myUDPServer.OnUDPRead := UDPRead;

LocalIPs := TStringList.Create;
try
  GStack.AddLocalAddressesToList(LocalIPs);
  for I := 0 to LocalIPs.Count-1 do
    myUDPServer.Bindings.Add.IP := LocalIPs[I];
finally
  LocalIPs.Free;
end;
{
Or this, if you are using an up-to-date Indy 10 snapshot:

LocalIPs := TIdStackLocalAddressList.Create;
try
  GStack.GetLocalAddressList(LocalIPs);
  for I := 0 to LocalIPs.Count-1 do
    myUDPServer.Bindings.Add.SetBinding(LocalIPs[I].IPAddress, myUDPServer.DefaultPort, LocalIPs[I].IPVersion);
finally
  LocalIPs.Free;
end;
}

myUDPServer.Active := True;
procedure TMyClass.DoUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
begin
  // ABinding.IP is the local IP address that received this packet...
end;