2014-06-25 118 views
-1

我有一個服務器和一個客戶端(德爾福)。Indy TCP服務器凍結,不知道爲什麼

客戶端獲取登錄詳細信息,然後連接到服務器將它們發送到服務器進行驗證,服務器接收數據驗證它,然後返回給定數據是否正確。

如果數據正確,客戶端會繼續到下一個窗口,在這個窗口中,他們將一些數據輸入到相應的字段中,然後將數據發送到服務器,當服務器接收到它存儲的數據時,然後回覆客戶端:存儲成功。當客戶端被通知數據存儲成功時,它會顯示一條消息通知用戶,然後終止。

當測試這個時,客戶端運行在四臺不同的計算機上(每臺計算機將打開和關閉客戶端大約6次),服務器突然停止響應客戶端(客戶端顯示消息「連接正常關閉」)

這是服務器返回錯誤: This is the error the server is returning
所以錯誤似乎是在ADOQuery打開執行SQL的連接,它爲什麼會只有30只後會執行一個例外?

任何建議我的問題是因爲我不知道它可能是什麼。 感謝您的幫助:)

+2

什麼阻止你調試呢?什麼阻止你自己調查你的想法? –

回答

4

如果客戶端收到「Connection closed gracefully」錯誤,則意味着服務器關閉了客戶端在服務器端的連接。如果你的服務器代碼沒有明確地這樣做,那麼它通常意味着在服務器的一個事件處理程序中引發了未捕獲的異常,這將導致服務器關閉套接字(如果在OnConnect事件之後和OnDisconnect之前引發異常事件,在套接字關閉之前觸發OnDisconnect)。 TIdTCPServer有一個OnException事件來報告該情況。

TIdTCPClient如果它仍處於打開狀態,則在銷燬過程中關閉套接字。

更新TIdTCPServer是一個多線程組件。每個客戶端連接都在自己的線程中運行。 ADO使用與創建它們的線程綁定的公寓線程COM對象,並且只能在該線程上下文中使用,除非使用CoMarshalInterThreadInterfaceInStream() + CoGetInterfaceAndReleaseStream()IGlobalInterfaceTable接口跨線程邊界進行封送處理。

在這種情況下,你應該:

  1. 給每個客戶自己的ADO連接和查詢對象。你既可以:

    A.在OnConnect事件創建它們並讓它們在TIdContextOnExecute事件中使用內儲存,然後釋放它們在OnDisconnect eventt。或者根據需要在OnExecute事件中創建並釋放它們。

    B.從TIdThreadWithTask派生新類並覆蓋其虛擬BeforeExecute()AfterExecute()方法來創建和免費ADO對象,然後分配TIdSchedulerOfThread...組件到TIdTCPServer.Scheduler財產之一,你的線程類分配到TIdSchedulerOfThread.ThreadClass財產。然後,在服務器事件中,可以使用TMyThreadClass(TIdYarnOfThread(TIdContext.Yarn).Thread)訪問調用線程的ADO對象。

  2. 創建一個單獨的ADO對象池。當客戶端需要訪問數據庫時,讓它將相應的ADO對象編組到調用線程的上下文中,然後在完成時將對象放回池中。

無論哪種方式,因爲ADO是基於COM的,不要忘記呼籲需要訪問ADO對象的每個客戶端線程CoInitialize/Ex()CoUnintialize(),無論是在OnConnectOnDisconnect事件,或在TIdThreadWithTask.BeforeExecute()TIdThreadWithTask.AfterExecute()方法。

+0

請再次檢查問題我添加了我在服務器端得到的錯誤的屏幕截圖 – Craig

相關問題