2011-05-04 52 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