Delphi 6 indy连接悬挂
我有个小问题。在我建立了服务器和客户端之间的连接之后。我会先关闭客户端,然后关闭服务器,但服务器挂起并向我发送“程序已崩溃”消息。我认为我遇到的问题是服务器无法识别客户端已断开连接,并且仍然认为客户端处于活动状态。以下是源代码: 客户:Delphi 6 indy连接悬挂,delphi,sockets,indy,Delphi,Sockets,Indy,我有个小问题。在我建立了服务器和客户端之间的连接之后。我会先关闭客户端,然后关闭服务器,但服务器挂起并向我发送“程序已崩溃”消息。我认为我遇到的问题是服务器无法识别客户端已断开连接,并且仍然认为客户端处于活动状态。以下是源代码: 客户: unit client; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ScktComp, Win
unit client;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, Winsock, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient;
type
TForm1 = class(TForm)
IdTCPClient1: TIdTCPClient;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetIpFromDns(HostName: string): string;
type
tAddr = array[0..100] of PInAddr;
pAddr = ^tAddr;
var
I: Integer;
WSA: TWSAData;
PHE: PHostEnt;
P: pAddr;
begin
Result := HostName;
WSAStartUp($101, WSA);
try
PHE := GetHostByName(pChar(HostName));
if (PHE <> nil) then
begin
P := pAddr(PHE^.h_addr_list);
I := 0;
while (P^[i] <> nil) do
begin
Result := (inet_nToa(P^[i]^));
Inc(I);
end;
end;
except
end;
WSACleanUp;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
IdTCPClient1.Host := GetIpFromDns('example.no-ip.org');
IdTCPClient1.Port := 9000;
IdTCPClient1.Connect;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if IdTCPclient1.Connected = True then
IdTCPClient1.Disconnect
else
end;
end.
看起来我并没有为indy设置监听端口,但我在object inspector页面中设置了。出于某种原因,如果我将IdTCPServer.DefaultPort和Active放在表单create中,它会抛出更多错误
我还尝试了IdTCPClient1.DisconnectSocket,但也没有成功
我是否需要在服务器端创建一些东西来定期检查连接?如果是这样,最好的方法是什么?在服务器线程的上下文中调用方法IdTCPServer1Connect。使用synchronize在主VCL线程中执行它。它是否与本地主机而不是GetIpFromDns('example.no ip.org')一起工作?为了进一步澄清mjn的评论,
ShowMessage
是VCL代码而不是线程安全的。您不需要GetIpFromDns()
。将Host
设置为example.no ip.org
并让Connect()
为您解决此问题。您应该手动解析的唯一原因是主机名有多个IP,在这种情况下,您应该循环连接到每个IP的每个IP,直到成功。但是,如果您只关心连接到一个IP,那么让Indy为您完成这项工作。此外,TIdTCPServer
需要分配OneExecute
事件处理程序,否则Active
属性设置程序将在运行时激活服务器时引发异常。
unit server;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, IdBaseComponent, IdComponent, IdTCPServer;
type
TForm1 = class(TForm)
IdTCPServer1: TIdTCPServer;
procedure IdTCPServer1Connect(AThread: TIdPeerThread);
procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
showmessage('client connected');
end;
procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
showmessage('client disconnected');
end;
end.