Delphi Indy TCP打孔,10061连接被拒绝
我正在开发一个P2P应用程序,需要启用一个 对于Rendezvous服务器,我正在使用一个简单的应用程序(在公共IP中运行),该应用程序具有启用SSL的Delphi Indy TCP打孔,10061连接被拒绝,delphi,indy,delphi-10.1-berlin,Delphi,Indy,Delphi 10.1 Berlin,我正在开发一个P2P应用程序,需要启用一个 对于Rendezvous服务器,我正在使用一个简单的应用程序(在公共IP中运行),该应用程序具有启用SSL的TIdTCPServer,该应用程序维护客户端连接并返回连接客户端的公共端点(AContext.Binding.PeerIP和AContext.Binding.PeerPort) 与服务器的客户端(TIdTCPClient)连接的属性ReuseSocket设置为rsTrue 这就是客户端连接到集合服务器的方式 当我尝试从B直接创建到客户端a的公共
TIdTCPServer
,该应用程序维护客户端连接并返回连接客户端的公共端点(AContext.Binding.PeerIP和AContext.Binding.PeerPort)
与服务器的客户端(TIdTCPClient
)连接的属性ReuseSocket设置为rsTrue
这就是客户端连接到集合服务器的方式
当我尝试从B直接创建到客户端a的公共端点的新连接时,就会出现此问题
TCP打孔代码
我收到套接字错误#10061连接被拒绝
所以,问题是如何建立到客户端公共端点的新连接而不引发异常 仅仅启用ReuseSocket=rsTrue是不够的。如果您更仔细地阅读链接文章,关于TCP打孔的部分将清楚地解释您的客户机需要一个侦听套接字和一个绑定在同一个本地端口上的出站连接套接字,该端口也用于与会合服务器进行通信。您显示的代码没有打开本地集合端口上的侦听套接字,也没有将出站P2P套接字端口绑定到本地集合端口。因此,在P2P套接字上使用
ReuseSocket
是没有用的。再次阅读文章。非常感谢@RemyLebeau的回复,我更新了问题,添加了客户端用于连接到会合服务器的代码。关于这个。。。您的客户端需要绑定在同一本地端口上的侦听套接字和出站连接套接字
不是充当侦听套接字的TCPClientMain
吗?否,TCPClientMain
不是侦听套接字。侦听套接字调用了BSDlisten()
函数TIdTCPClient
使用BSDconnect()
函数代替。在TCP中打孔时,每个客户端至少需要4个套接字-1个连接到集合服务器,1个本地侦听(TIdTCPServer
或TIdSimpleServer
),以及至少2个尝试连接到其他客户端的公共/私有端点。。。。。。所有4个套接字必须绑定到同一本地端口,这意味着在所有4个套接字上设置ReuseSocket=rsTrue
。然后,将TCPClientMain
连接到集合服务器后,可以使用TCPClientMain.Socket.Binding.Port
(而不是TCPClientMain.Port
)指定其他套接字的本地端口(在TIdTCPClient.BoundPort
、TIdTCPServer.DefaultPort
和TIdSimpleServer.BoundPort
属性中)。再次,请更仔细地阅读本文,这些要求已详细解释。您只需将详细信息映射到Indy等效项。您仍然缺少这方面的重要步骤。我强烈建议您首先不使用SSL来解决此问题。一旦您了解并验证了它的有效性,然后重新引入SSL。请确保在验证正确的客户端是否连接到其他客户端之前,您不会设置TIdSSLIOHandlerSocketOpenSSL.PassThrough=False
,因为打孔时建立连接后,您应该执行端点验证。。。
TCPClientMain.ConnectTimeout := 500;
TCPClientMain.Host := RendezvousServerIP;
TCPClientMain.Port := RendezvousServerPort;
TCPClientMain.UseNagle := false;
TCPClientMain.ReuseSocket := rsTrue;
OpenSSLHandlerMain.UseNagle := false;
OpenSSLHandlerMain.ReuseSocket := rsTrue;
TCPClientMain.IOHandler := OpenSSLHandlerMain;
TCPClientMain.Connect();
var
LTCPClient : TIdTCPClient;
LOpenSSLHandle : TIdSSLIOHandlerSocketOpenSSL;
begin
//Init the SSL for the new connection
LOpenSSLHandle := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
LOpenSSLHandle.SSLOptions.Method := TIdSSLVersion.sslvTLSv1_2;
LOpenSSLHandle.SSLOptions.SSLVersions := [sslvTLSv1_2];
LOpenSSLHandle.UseNagle := False;
LTCPClient := TIdTCPClient.Create(nil);
LTCPClient.ConnectTimeout := 5000;
//Set the data of the public end point of the Client A
LTCPClient.Host := ARemoteIPAddress; //This is the public ip of the Client A
LTCPClient.Port := ARemotePort; //This is the port of the public endpoint of the client A
LTCPClient.ReuseSocket := rsTrue;
LTCPClient.IOHandler := LOpenSSLHandle;
LTCPClient.Connect(); //This raises a EIdSocketError exception