2011-05-04 92 views
3

我有一个使用idHttpServer开发的web服务器应用程序。当一个客户端连接做我的网络服务器,并由于某种未知的原因,断开连接(不正常断开连接)我的网络服务器不会得到通知。我知道这是正常行为,但我需要知道客户何时死亡。TCP在idHttpServer(服务器)和wininet(客户端)上运行

有几种方法可以做到这一点。我知道2个好方法:

1 - 实现心跳机制。客户端套接字通知服务器它仍然存在(需要一些工作和一些代码才能使其工作)

2 - TCP Keep Alive。这是我最喜欢的方式,因为它不需要太多的代码和工作。但是我对此有几个问题。

  • 这可能与 idHttpServer(服务器)和 WinInet函数(客户端)使用吗?
  • 这是否真的按预期工作?我的意思是,当客户端一直死亡时服务器不满意?
  • 有没有人有在Wininet上设置此示例? (我想这必须在客户端进行设置,对不对?)
  • 是否有通知服务器客户端已经死了一个更好的方式(利用Indy和WININET,当然)

编辑

我使用德尔福2010年和最后Indy10源代码从他们的SVN。

回答

2

如果你是使用了最新的Indy 10版本,那么你可以使用TIdSocketHandle.SetKeepAliveValues()方法:

procedure SetKeepAliveValues(const AEnabled: Boolean; const ATimeMS, AInterval: Integer); 

例如:

procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext); 
begin 
    // send a keep-alive every 1 second after 
    // 5 seconds of inactivity has been detected 
    AContext.Binding.SetKeepAliveValues(True, 5000, 1000); 
end; 

注意,ATimeMSAInterval参数仅在Win2K和更高版本上受支持。

否则,直接使用TIdSocketHandle.SetSockOpt()方法来手动启用TCP/IP SO_KEEPALIVE选项:

procedure TIdSocketHandle.SetSockOpt(ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; AOptVal: Integer); 

例如:

procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext); 
begin 
    AContext.Binding.SetSockOpt(Id_SOL_SOCKET, Id_SO_KEEPALIVE, 1); 
end; 
+0

这样,印地应该叫OnDisconnect事件?如果是这样,这是行不通的。如果我拔掉网线IDHttpServer不会调用OnDisconnect事件。 – 2011-05-05 13:03:41

+0

只有当套接字拥有的线程停止时,OnDisconnect才会被触发。在操作系统报告套接字错误之前,Indy无法知道它是死锁连接。并非所有的操作系​​统版本都会将电缆拉出立即视为丢失的连接,所以即使启用了Keepalive,在操作系统最终停止尝试之前,也必须等待几次keepalive。这需要时间。然后它开始报告套接字上的错误,Indy可以在下次访问套接字时检测并引发异常。确保你没有吞下Indy在你的代码中的例外,让他的服务器处理它们。 – 2011-05-06 08:11:28