Delphi XE3 - Reuse socket rsTrue 在任何情况下都会被系统覆盖吗?

Posted

技术标签:

【中文标题】Delphi XE3 - Reuse socket rsTrue 在任何情况下都会被系统覆盖吗?【英文标题】:Delphi XE3 - Does Reuse socket rsTrue get overridden by system in any case? 【发布时间】:2014-04-24 09:58:57 【问题描述】:

最近我做了一些非常小、非常轻的应用程序,它使用两个 UDP 客户端和两个 UDP 服务器组件。除了几个功能之外,它基本上没有其他功能。 我被“无法绑定套接字。地址和端口已在使用中”卡住了一段时间,但不知何故通过更改端口解决了这个问题,在 Reuse Socket 上使用 rsTrue 属性,但不知何故,几个用户在尝试运行时仍然遇到该错误来自应用程序的连接。

服务器和客户端必须使用相同的端口和相同的地址,因为 UDPClient 需要 BoundPort 与 UDPServer 的绑定端口相同。这是因为响应被发送到请求来自的同一端口。这导致了主要错误,已通过 rsTrue 属性解决。

现在我想知道,系统是否有可能通过某些我不熟悉的东西覆盖此设置?因为到目前为止,在我测试过的 12 台计算机上,它运行良好(在一台计算机上,我不得不终止 Bonjour 服务,因为它使用的是我需要的确切端口,但除此之外......)

否则会导致什么错误?

这些是在单击连接按钮时调用的设置:

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;

其中 Port 是 TEdit 字段供用户输入端口,DeviceIP 是设备的 IP,Interface 是他将使用的本地网络接口 IP。

唯一不需要硬编码的硬编码是LocalClient.BoundPort:=10024,它只是为了使GUI尽可能轻。但改变这一点也无济于事。

该应用是PC上原始应用与网络设备之间的代理服务器。

10023 必须按原样设置,因为设备只侦听该端口,而原始应用程序只发送到该端口!

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

您不需要在同一端口上使用单独的 TIdUDPClientTIdUDPServer。您可以单独使用TIdUDPServer 并让它处理发送和接收。根本不需要使用单独的TIdUDPClient

另外,您没有正确使用Binding 属性。当您第一次读取服务器的Binding 属性时,使用服务器的Bindings 集合中的设置绑定套接字。然后忽略您对Binding.IPBinding.Port 的分配。您需要先配置服务器的Bindings 集合,然后使用服务器的Binding 属性仅用于发送(服务器将为您处理读取)。

试试这个:

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);

回复将到达服务器的OnUDPRead 事件。

顺便说一句,既然您正在编写代理,请查看TIdMappedPortUDP 组件。

【讨论】:

会看看这个。我已经使用了 OnUDPRead,但不知道我也可以使用它来发送数据。谢谢你。另外,至于绑定,我都尝试过,使用 bindings.add.IP 和 port,然后在启动时设置一些默认值,ant 使用 bindings[0].IP 和 port 替换它们,然后使用绑定,这很好经过一些处理...... 套接字绑定后不能替换IP/端口。您必须停用并重新激活服务器才能更改它们。 可是我在激活前改了..?没有区别吗? 否,因为您使用Binding 属性(单数)进行更改,并且访问Binding 会导致套接字在您更改它们之前与现有值绑定。绑定后更改 IP/端口不会将新值应用于绑定的套接字。您想要进行的任何更改都必须改为对Bindings 属性(复数)进行,然后通过(re)activation 应用。 似乎解决了。如您所说,使用服务器发送数据。感谢这个提示!

以上是关于Delphi XE3 - Reuse socket rsTrue 在任何情况下都会被系统覆盖吗?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi XE3 尝试释放 FSQL (TStringList) 时指针无效

把exe嵌入到自己的exe中。delphi xe3

Delphi XE3 Ctrl+Z 也可以撤消插入符号的移动

socket reuse

socket设置地址复用

在delphi中XLSReadWriteII.组件的应用实例