西雅图的 UDP vs Delphi 7

UDP in Seattle vs Delphi 7

这段代码在Delphi 7:

下运行良好
procedure TForm1.FormCreate(Sender: TObject);
   //var    IdUDPClient1: TIdUDPClient;
   begin
     idudpclient1.host := '127.0.0.1';
     idudpclient1.port := 1234;
     idudpclient1.Binding.Port := 1234;
     idudpclient1.Binding.Bind;
     idudpclient1.Send('Hello');
   end;

运行 完全相同的代码 Delphi 10 Seattle 32 位 windows 给出套接字运行时错误 10022:参数无效, 接着 无法绑定套接字,地址和端口已被使用。

有什么想法吗?

此致 托马斯·里德尔

在 Indy 10 中,当您访问 Binding 属性 时,将创建套接字 并绑定 如果尚未创建。因此,您正在尝试在已绑定的套接字上调用 Bind()

当基础套接字 API bind() 失败时,会引发 "Invalid argument" 错误。根据 MSDN 的 bind() 文档:

WSAEINVAL
An invalid argument was supplied.

This error is returned of the socket s is already bound to an address.

TIdSocketHandle.Bind() 调用 TIdSocketHandle.TryBind(),并且 TryBind() 捕获 "Invalid argument" 错误,因此只有当您 运行 您的代码在调试器。 "Could not bind socket" 错误是 Indy 自己的错误,TIdSocketHandle.Bind()TryBind() 失败时引发。

您根本不应该直接设置 Binding.Port,或直接调用 Binding.Bind()。使用 TIdUDPClient.BoundPort 属性(也可以选择 TIdUDPClient.BoundIP)代替:

procedure TForm1.FormCreate(Sender: TObject);
//var    IdUDPClient1: TIdUDPClient;
begin
  IdUDPClient1.Host := '127.0.0.1';
  IdUDPClient1.Port := 1234;
  //IdUDPClient1.BoundIP := '127.0.0.1';
  IdUDPClient1.BoundPort := 1234;
  IdUDPClient1.Send('Hello');
end;

TIdUDPClient分配套接字时,它会为你调用Bind(),将BoundPort分配给Binding.PortBoundIP分配给Binding.IP).

您的代码在 Delphi 7 中工作的原因是因为您使用的是 Indy 9(或更早版本)而不是 Indy 10。在那些更早的 Indy 版本中,访问 Binding 属性 只分配了套接字,它没有绑定套接字,因此您可以手动绑定它。现在已经不是这样了。