2009-11-02 215 views
0

我正在處理客戶端服務器應用程序。客戶端不斷從服務器讀取數據,因此當服務器關閉或斷開時,客戶端崩潰。我嘗試了一個try/catch塊,但它不起作用。我的客戶端應用程序是用C++編寫的。我希望客戶端顯示一些正確的消息,如「服務器斷開連接」,然後退出。客戶端如何正常檢測服務器何時斷開連接?

+5

你有一個很好的代碼片段? – sharptooth 2009-11-02 13:12:46

+1

你能給我們提供更多的細節,代碼示例可能嗎? – varnie 2009-11-02 13:34:34

+1

我建議你不僅添加一段代碼給我們一些跡象,說明你的try/catch爲什麼不起作用,還有一些關於你的客戶端與服務器通信的信息(socket?[D] COM?CORBA [別笑!]?網絡服務?其他?)。描述當你試圖捕捉異常時究竟發生了什麼也是有幫助的:某種形式的try/catch應該可以解決這個問題,除非你使用了一些......異常......遠程庫。 – 2009-11-02 13:38:38

回答

0

看一下Code Project Len Holgates的東西 - he hangs out here too。他是插座上的大腦和他的IOCP的東西是我見過的最好的,我知道他的東西不正是你在找什麼。

+3

-1。聽起來像「使用Google」。 – 2009-11-02 13:28:38

+1

+1:不,不。 – 2009-11-02 13:38:40

+1

請提供更具體的鏈接,例如Holgates解釋這個問題的答案的文章。 – 2009-11-02 19:55:56

0

推廣異常處理來處理拋出的任何類型的異常;

try 
{ 
// try something 
} 
catch(...) 
{ 
// handle exception 
} 

處理特定類型的異常,如COM異常

try 
{ 
//try something 
} 
catch(_com_error &e) 
{ 
// handle exception 
} 

你也可以去MSDNHERE更詳細的信息。

+0

如果你的套接字讀取沒有拋出異常,你需要這樣做才能使catch生效。看看這個更多的信息 - http://www.cplusplus.com/doc/tutorial/exceptions/。 – zooropa 2009-11-02 13:45:36

1

沒有關於錯誤的更多細節,我們都只是猜測。

是什麼讓你相信異常導致錯誤?

如果使用堆棧安全檢查進行編譯,它可能是分段錯誤或訪問衝突或堆棧粉碎。

如果套接字處理中的某些內容覆蓋主處理函數的返回地址,則很容易發生這種情況。當套接字關閉時,處理函數將會崩潰。

或者它可能是由雙重空閒或通過寫入已釋放的內存導致的堆內存損壞。

0

你還沒有告訴我們很多,所以我不得不做一些猜測。

在C++中,不像Java或C#中那樣使用異常,其中(幾乎)所有錯誤處理都是使用異常完成的。在C++中,還有一些其他獨立的機制也需要使用。

如果您在Java中出現空指針錯誤,Java將拋出一個NullPointerException,您可以使用try-catch塊捕獲該錯誤。在C++中,你會得到一個分段錯誤(或者不是,或者別的,這取決於你正在使用的是哪個操作系統),其中而不是被try-catch塊捕獲。這是完全不同的機制。

如果您嘗試將文本字符串轉換爲數字,但不起作用,Java將引發NumberFormatException。在C++中,你必須事後檢查它是否工作。 try-catch塊不會幫助你。

所以,只要將你的庫調用放在try-catch塊中就可能沒有幫助。如果你的套接字庫在服務器關閉時沒有拋出異常(我認爲它不太可能),那麼幾乎可以肯定有其他一些方法來檢查它。也許有讀取調用的返回值,如果套接字的另一端已關閉,則該值爲負值?

如果您沒有檢查關閉的套接字,並且您的程序不斷嘗試讀取並處理收到的數據,就好像套接字仍然打開一樣,程序很可能會崩潰。但是,這種崩潰也不能通過嘗試抓取來處理。

總而言之,try-catch可能是解決問題的錯誤方法,您需要檢查套接字庫的文檔以瞭解如何執行此操作。

1

我不確定你在哪個平臺上運行,但如果它是基於Unix的平臺,那麼你可能會遇到一個「特性」,遠程關閉的TCP連接會導致你的客戶端SIGPIPE信號,當它試圖寫入套接字。如果SIGPIPE信號未處理(除非您明確安裝了處理程序),則未處理的信號將導致程序終止。

避免這個問題的最簡單方法是包含在這個程序的開頭:

#include <signal.h> 

// [... somewhere near the top of main(), perhaps ...] 
signal(SIGPIPE, SIG_IGN); 

一旦做到這一點,已關閉的連接將更加微妙的方式傳達給你,例如select()返回準備好讀取,然後recv()返回0(意味着EOF)。

SIGPIPE無法在Windows下發生的,所以如果你的程序僅適用於Windows,你可以忽略這個帖子:)

相關問題