IdTcpServer无法在CentOS+;下的context.connection.disconnect()之后释放其上下文线程;拉撒路
在单击BTDISCON按钮后,Memo1的结果仍然是“connct:1”,尽管我等待了几分钟 但是在windows xp下,它可以正常工作,如何让idtcpserver删除无效的上下文线程 这是我的密码: 客户端(Windows7+DelphiXE2+Indy10.5.8): 服务器端(Vmware+CentOS+Lararus1.0.12+Indy10.5.8)IdTcpServer无法在CentOS+;下的context.connection.disconnect()之后释放其上下文线程;拉撒路,centos,lazarus,indy10,Centos,Lazarus,Indy10,在单击BTDISCON按钮后,Memo1的结果仍然是“connct:1”,尽管我等待了几分钟 但是在windows xp下,它可以正常工作,如何让idtcpserver删除无效的上下文线程 这是我的密码: 客户端(Windows7+DelphiXE2+Indy10.5.8): 服务器端(Vmware+CentOS+Lararus1.0.12+Indy10.5.8) 服务器代码存在两个问题,无法正常关闭: 您的OnExecute代码正在捕获并丢弃所有异常,并且不允许TIdTCPServer处理任何
服务器代码存在两个问题,无法正常关闭:
OnExecute
代码正在捕获并丢弃所有异常,并且不允许TIdTCPServer
处理任何异常。停用TIdTCPServer
时,它会关闭所有活动套接字,从而导致当前/后续套接字操作失败并引发异常。通过丢弃异常,TIdTCPServer
不知道连接已经关闭,并且愉快地继续调用OnExecute
事件。如果必须捕获异常(例如记录异常),则需要在处理完异常后重新引发任何Indy特定的异常,以便TIdTCPServer
可以处理它们TMemo
,这可能(除其他外)导致死锁uses
..., IdSync;
type
TMemoNotify = class(TIdNotify)
protected
FMsg: String;
procedure DoNotify; override;
public
class procedure AddToMemo(const AMsg: string);
end;
procedure TMemoNotify.DoNotify;
begin
Form1.Memo1.Lines.Add(FMsg);
end;
class procedure TMemoNotify.AddToMemo(const AMsg: string);
begin
with Create do
begin
FMsg := AMsg;
Notify;
end;
end;
除了重新引发Indy异常之外,您还可以完全取消OnExecute
事件中的异常处理,并使用TIdTCPServer.OnException
事件:
procedure TForm1.TcpServerExecute(AContext: TIdContext);
var
b: Byte;
begin
b := AContext.Connection.IOHandler.ReadByte;
...
end;
procedure TForm1.TcpServerException(AContext: TIdContext; AException: Exception);
begin
TMemoNotify.AddToMemo('Error:'+AException.Message);
end;
OT:移动行
lst:=TcpServer.Contexts.LockList()
和lst:=TcpServer.Contexts.LockList()在之前尝试关键字。在调用Disconnect()
之后不要调用DiscardAll()
,因为套接字现在已关闭,因此无法读取更多数据。如果您只想清除InputBuffer
,那么直接执行:itm.Connection.IOHandler.InputBuffer.clear代码>
uses
..., IdSync;
type
TMemoNotify = class(TIdNotify)
protected
FMsg: String;
procedure DoNotify; override;
public
class procedure AddToMemo(const AMsg: string);
end;
procedure TMemoNotify.DoNotify;
begin
Form1.Memo1.Lines.Add(FMsg);
end;
class procedure TMemoNotify.AddToMemo(const AMsg: string);
begin
with Create do
begin
FMsg := AMsg;
Notify;
end;
end;
uses
..., EIdException;
procedure TForm1.FormShow(Sender: TObject);
var
Bind: TIdSocketHandle;
begin
TCPServer.Bindings.Clear;
Bind := TCPServer.Bindings.Add;
Bind.IPVersion := Id_IPv4;
Bind.Port := 10000;
TcpServer.OnExecute := TcpServerExecute;
TcpServer.Active := True;
Timer1.Interval := 5000;
Timer1.Enabled := True;
end;
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
Timer1.Enabled := False;
TcpServer.Active := False;
end;
procedure TForm1.TcpServerExecute(AContext: TIdContext);
var
b: Byte;
begin
try
b := AContext.Connection.IOHandler.ReadByte;
except
on E: Exception do
begin
TMemoNotify.AddToMemo('Error:'+E.Message);
if E is EIdException then raise;
end;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
lst: TList;
begin
lst := TcpServer.Contexts.LockList;
try
Memo1.Lines.Add('ConnCnt:'+IntToStr(lst.Count));
finally
TcpServer.Contexts.UnlockList;
end;
end;
procedure TForm1.btDisconnClick(Sender: TObject);
var
i: Integer;
lst: TList;
begin
lst := TcpServer.Contexts.LockList;
try
for i := 0 to lst.Count-1 do
begin
try
TIdContext(lst.Items[i]).Connection.Disconnect;
except
end;
end;
finally
TcpServer.Contexts.UnlockList;
end;
end;
procedure TForm1.TcpServerExecute(AContext: TIdContext);
var
b: Byte;
begin
b := AContext.Connection.IOHandler.ReadByte;
...
end;
procedure TForm1.TcpServerException(AContext: TIdContext; AException: Exception);
begin
TMemoNotify.AddToMemo('Error:'+AException.Message);
end;