Delphi TIdTCPServer在第二次连接时卡住
我正在使用TIdTCPClient获取文件列表,所有这些都可以正常工作,但是当我关闭客户端应用程序并再次打开它时,我在TCPServer OneExecute上没有收到任何事件,尽管TIdTCPClient成功连接到它,并且我无法发送文件列表 我做错了什么 一些代码:Delphi TIdTCPServer在第二次连接时卡住,delphi,indy,Delphi,Indy,我正在使用TIdTCPClient获取文件列表,所有这些都可以正常工作,但是当我关闭客户端应用程序并再次打开它时,我在TCPServer OneExecute上没有收到任何事件,尽管TIdTCPClient成功连接到它,并且我无法发送文件列表 我做错了什么 一些代码: procedure TTaifun.csConnected(Sender: TObject); begin cs.IOHandler.WriteLn('FILE_LIST|NOW'); //Sending a request
procedure TTaifun.csConnected(Sender: TObject);
begin
cs.IOHandler.WriteLn('FILE_LIST|NOW'); //Sending a request to server for the files
fname := cs.IOHandler.ReadLn(nil); //Got the file names
files := ExplodeString(fname,'|'); // Parse the files
end;
procedure TTaifun.svExecute(AContext: TIdContext);
var
cmds, flist: TStringList;
i: Integer;
tmp: string;
FS : TFileStream;
begin
CSection.Enter; //Enter critical section
cmds := ExplodeString(AContext.Connection.IOHandler.ReadLn(nil), '|');
try
if cmds[0] = 'FILE_LIST' then //Check command received
begin
flist := TStringList.Create;
flist.LoadFromFile(MyPath + 'files.dat');
tmp := '';
for i := 0 to flist.Count - 1 do
begin
tmp := tmp + flist[i] + ',' + GetFileSize(flist[i]) + ',' +
BoolToStr(FileExists(MyPath + 'Thumbs\' +
ChangeFileExt(ExtractFileName(flist[i]), '.thb')),true) + '|'; //Do some parsing
end;
AContext.Connection.IOHandler.WriteLn(tmp); //Send the string
end
finally
CSection.Leave; //Leave critical section
end;
end;
您没有保护您的关键部分不受异常的影响。当客户端断开连接时,
ReadLn()
或WriteLn()
(取决于时间)将引发异常,以终止该客户端的线程。下次为其他线程调用OnExecute
事件时,关键部分仍将被锁定,无法再次输入,从而导致代码死锁。在代码中添加一个try/finally
,以防止出现这种情况,例如:
procedure TTaifun.svExecute(AContext: TIdContext);
var
...
begin
CSection.Enter; //Enter critical section
try
...
finally
CSection.Leave; //Leave critical section
end;
end;
既然如此,为什么要从关键部分开始呢?您显示的代码本身是线程安全的,不需要对其进行并发访问保护:
procedure TTaifun.svExecute(AContext: TIdContext);
var
cmds, flist: TStringList;
i: Integer;
tmp: string;
begin
cmds := ExplodeString(AContext.Connection.IOHandler.ReadLn, '|');
if cmds[0] = 'FILE_LIST' then //Check command received
begin
tmp := '';
flist := TStringList.Create;
try
flist.LoadFromFile(MyPath + 'files.dat');
for i := 0 to flist.Count - 1 do
begin
tmp := tmp + flist[i] + ',' + GetFileSize(flist[i]) + ',' +
BoolToStr(FileExists(MyPath + 'Thumbs\' +
ChangeFileExt(ExtractFileName(flist[i]), '.thb')),true) + '|'; //Do some parsing
end;
finally
flist.Free;
end;
AContext.Connection.IOHandler.WriteLn(tmp); //Send the string
end;
end;
或者:
procedure TTaifun.svExecute(AContext: TIdContext);
var
cmds, flist: TStringList;
i: Integer;
begin
cmds := ExplodeString(AContext.Connection.IOHandler.ReadLn, '|');
if cmds[0] = 'FILE_LIST' then //Check command received
begin
flist := TStringList.Create;
try
flist.LoadFromFile(MyPath + 'files.dat');
for i := 0 to flist.Count - 1 do
begin
flist[i] := flist[i] + ',' + GetFileSize(flist[i]) + ',' +
BoolToStr(FileExists(MyPath + 'Thumbs\' +
ChangeFileExt(ExtractFileName(flist[i]), '.thb')),true); //Do some parsing
end;
flist.Delimiter := '|';
flist.StrictDelimiter := True;
AContext.Connection.IOHandler.WriteLn(flist.DelimitedText); //Send the string
finally
flist.Free;
end;
end;
end;
请参阅作者对此的评论。它与TIdHTTP相关,但可能会让您了解问题所在。对你的Delphi和Indy版本进行精确化,并提供一些代码,这将有助于人们愿意回答你的问题。真的,你在这里问了足够多的问题,知道如果你不提供更多细节,没有人能帮助你。。。比如…,哦,我不知道,也许是一些代码?@Marjannema我不喜欢你的态度,我很好奇你现在是否有解决办法。很难。我不喜欢你老是问问题,等别人问更多的细节,然后再提供足够的信息让别人帮助你。在您添加的代码中,您不知道TTaifun是从何而来的,也不知道它是服务器端还是客户端,也不知道其他可能帮助您的东西。虽然我可以做一个受过教育的任务,但我不会去打扰,我不应该去…@Marjannema不要打扰我舒尔不会错过任何东西:)