TIdTCPServer 在有客户端连接的情况下,要怎么关闭比较好?我现在直接把Active赋为false,要出错。(50分)

  • 主题发起人 主题发起人 ansili
  • 开始时间 开始时间
A

ansili

Unregistered / Unconfirmed
GUEST, unregistred user!
TIdTCPServer 在有客户端连接的情况下,要怎么关闭比较好?没异常。
我现在直接把Active赋为false,要出错。
 
先断开客户端连接
 
在Indy 中 大部分 异常,不叫出错,Indy 很多功能依赖 exception 来进行处理。
 
你接管它的 异常处理就行了(处理异常事件)。
处理完成后,传回错误码进去到Indy内部就可以了, 就不会弹出奇怪的错误。
 
destructor TBaseTCPServer.Destroy;
begin
try
TCPServer.Active := false;
except on Ex : Exception do
AppendLog('停止端口监听(Destroy) : ' + IntToStr(TCPServer.DefaultPort) + ' 失败,ErrorInfo' + Ex.Message);
end;
........
end;
这样处理了啊。
还是要出错:Terminate Thread Timeout,而且没断开。

To : jfyes
处理完成后,传回错误码进去到Indy内部就可以了。怎么传,能给出示例代码吗?

我的 QQ:69786714;MSN:ansili@hotmail.com
 
uses
IdException, IdStackConsts;

procedure TForm1.IdTCPServer1Exception(AThread: TIdPeerThread;
AException: Exception);
begin
ShowMessage(AException.Message);
{ case EIdSocketError(AException).LastError of
//// .....
// 处理相应异常
end;
}
//呵呵,这里原以为像TSocketServer里面,不能直接将错误码更改。
//看到你上面出现的Terminate Thread Timeout应该是线程里面关闭Socket异常,这个异常处理过程也扑捉不到的。
//TerminateWaitTime 属性值设长一点。可能是你的关闭Socket之前有数据要发送,所以超时。这只是猜测。
//procedure TIdTCPServer.TerminateAllThreads;你跟综这个过程看看里是怎么关闭线程的。
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
try
IdTCPServer1.Active := False;
except
On E: Exception do //在这里屏闭,不它弹出
//ShowMessage(E.Message);
end;
end;
 
我试试。
是不是让主动客户端开是比较好的方法?
TerminateWaitTime设置多大比较合适
 
To : jfyes
我将这个(TerminateWaitTime)设置为30秒,结果还是有这个错误(Terminate Thread Timeout),而且没断开。

有什么好的方法吗?
 
EIdTerminateThreadTimeout
1.应该是多线程程序某个线程不能正常结束,
只有所有的附加线程都停止了
主线程才能正常结束进程运行

2. 服务线程设计得有问题,OnExecute没有结束,那里不需要做成死循环,indy的线程管理会自动循环调用它,如果一定要做成了死循环,就要自己来判断该什么时候退出了。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1873932

这个贴子可能就是你的原因吧? http://www.delphibbs.com/delphibbs/dispq.asp?lid=2086401
 
呵呵,是你的线程OnExecute过程里的问题,刚才我又重新试了。
在线程内数据读写完成关闭线程,就没有问题了。
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin

AThread.FreeOnTerminate := true;
AThread.Connection.ReadBuffer(Abuffer, 1024);
AThread.Connection.WriteBuffer(Sendbuffer, 1024);
AThread.Terminate;
end;
 
To : jfyes
非常感谢你.
OnExecute在客户端异常断开(Socket 10054)的时候那我用这个方法(AThread.Connection.ReadFromStack(true,10,false))获得包大小造成异常,而且没有终止线程。
我现在TCPServerOnExecute事件是这样处理的。
AThread.FreeOnTerminate := true;
try
tmpBufferLen := AThread.Connection.ReadFromStack(true,10,false);
except on Ex : Exception do
begin
AThread.Connection.Disconnect;
AThread.Terminate;
AppendLog('TCPServerExecute ReadFromStack : ' + Ex.Message);
end;
end;
而且我服务端如果主动断开的话,我做一个标志,不让客户端来连接。

但即使这样有时候在停止监听(IdTCPServer1.Active := false)的时候,还是有异常。程序安全退出不了。我想是不是这样我在停止监听的时候还有线程没结束造成的还是其他原因呢,如果是这样那怎么判断所有线程(IdTCPServer1开启的)结束呢?

你有即时通讯ID吗?我们交流一下。我的:qq : 69786714,MSN:ansili@hotmail.com
 
QQ很少在线,大部分时间在网上。
// uses IdThreadSafe;
procedure TForm1.Button1Click(Sender: TObject);
begin
//if IdTCPServer1.Threads.LockList.Count > 0 then ///这就是线程列表
if TIdThreadSafeList(IdTCPServer1.Threads).IsCountLessThan(1) then
// 线程全部释放

但是这样判断要先手动关闭线程,你在IdTCPServer1.Active := false属性时,INDY内
部结束线程了(没有结束是因为你的线程TCPServerOnExecute有问题),就不用你在判断了,即然这样也没有必要手动关闭线程了。
 
这是我TCPServerOnExecute的全部代码,你看看有什么问题?

var
ErrorStr : String;
DataBuf : TMyDataBuffer;
tmpBuffer : PChar;
tmpBufferLen : integer;
xx : Cardinal;
begin
AThread.FreeOnTerminate := true;
if (not AThread.Terminated) and (AThread.Connection.Connected) then
begin
tmpBufferLen := 0;
try
tmpBufferLen := AThread.Connection.ReadFromStack(true,10,false);
except on Ex : Exception do
begin
DisconnectTCPClient(AThread);
AThread.Terminate;
AppendLog('TCPServerExecute ReadFromStack : ' + Ex.Message);
end;
end;
if tmpBufferLen > 0 then
begin
try
DataBuf := TMyDataBuffer.Create(tmpBufferLen);
AThread.Connection.ReadBuffer(DataBuf.BufferData[0],DataBuf.BufferLength); //读取SOCKET数据
AddToReceiveQueue(DataBuf); //添加到接收队列
except
on Ex : Exception do
begin
FreeAndNil(DataBuf);
ErrorStr := Ex.Message;
AppendLog('TCPServerExecute Error : ' + ErrorStr);
end;
end;
end;
end;
 
DataBuf.会不会引发异常,正常情况没有释放,你可能放在队列中, 遵守谁创建谁释放的规则,以免引不必要的错误。

下面一个try excetp end 加上
DisconnectTCPClient(AThread);
AThread.Terminate;
================================
 
DataBuf是由另外一个线程来出来,处理完就释放。
 
TCPServerException 事件需要做什么处理?
 
师兄能告诉我你的客户端怎么读取服务器端的用户ACCESS信息数据库的呢
用ADO?怎么写连接接口的?
 
除了以上在TCPServerOnExecute应该注意代码外,还可以在Form.close事件中做如下处理:

var i:integer;
begin
for i:=0 to 5 do
begin
try
IdTCPServer1.Active := False;
except
sleep(1000); //如果有错误,嘿嘿,暂时休息一下,时间和循环次数有你自己定。
//怎么样,野蛮吧!
end;
end;
end;
 
多些各位,但是在听监听(IdTCPServer1.Active := False;)的时候要是有错误。
 
接受答案了.
 
后退
顶部