DIOCP3 服务器当客户端有很多连接不断开时退出卡

jingzu

Registered
Registered
2000个连接并读写数据库。
客户端先断开连接,即 FOnlineContextList.Count=0 时,IocpTcpServer1.Active := false;没事。
如果FOnlineContextList.Count>0 时,则IocpTcpServer1.Active := false会卡死,无法释放。

IocpTcpServer1.DisconnectAll;
也卡死。
IocpTcpServer1.free
也卡死。
如果客户端断开了,FOnlineContextList.Count=0,就不会卡死了。
所以看样子:IocpTcpServer1无法主动断开,必需等客户端全部断开才能
IocpTcpServer1.Active := false

 

jingzu

Registered
Registered
折腾了两天了。
现在暂时解决方法:
destructor TmainForm.Destroy;
begin
IocpTcpServer1.OnDataReceived:=nil;
// DisconnectAll;
// IocpTcpServer1.DisconnectAll;
inherited Destroy;
end;
然后在
procedure TmainForm.IocpTcpServer1DataReceived(
pvClientContext: TIocpClientContext; buf: Pointer; len: Cardinal;
errCode: Integer);
begin
try
IocpTcpServer1.Locker.lock();
if not assigned(IocpTcpServer1.OnDataReceived) then
begin
pvClientContext.DoDisconnect;
exit;
end;

finally
IocpTcpServer1.Locker.unLock();
// LeaveCriticalSection(MyCs); //离开临界区

end;
end;
顺利退出。
 

天地弦

Moderator
管理成员
Moderator
首先,要明白一点, DIOCP的所有事件都是在线程中触发的。

然后再来看. Active := false, 会做些什么事情。
1.通知关闭所有连接。注意是通知。也就是说不会强制结束线程。
2.等待连接对象回归到对象池, 也就是说,如果连接正在处理逻辑,会等到逻辑结束后才会回归。

如果逻辑处理的时候造成资源访问冲突而造成死锁,那么Active := false的时候会等待120秒后,强制关闭线程,并记录连接的状态到日志文件,这个时候可以看看日志文件,看看死锁的原因。

 

天地弦

Moderator
管理成员
Moderator
procedure TmainForm.IocpTcpServer1DataReceived(
pvClientContext: TIocpClientContext; buf: Pointer; len: Cardinal;
errCode: Integer);
begin
try
IocpTcpServer1.Locker.lock();
if not assigned(IocpTcpServer1.OnDataReceived) then
begin
pvClientContext.DoDisconnect;
exit;
end;

finally
IocpTcpServer1.Locker.unLock();
// LeaveCriticalSection(MyCs); //离开临界区

end;
end;

//// 你这种做法也会有问题,你这个用了个全局锁,这样导致所有的逻辑都是串行的
 

天地弦

Moderator
管理成员
Moderator
你可以贴一下你读取数据库的代码。
你想一下,你如果2000个并发,然后后台串行执行2000个逻辑,会有很大的延时的。这样做还不如单线程处理,没必要用iocp
 

Similar threads

顶部