1. 程式人生 > >Android native程序間通訊例項-socket本地通訊篇之——服務端程序異常退出解決辦法

Android native程序間通訊例項-socket本地通訊篇之——服務端程序異常退出解決辦法

 導讀:

  好難受啊,為什麼服務端說掛就掛,明明只是客戶端關閉而已,服務端怎麼能掛呢?

想想,如果手機上使用一個聊天程式的時候,手機端關閉了聊天程式,那麼遠端伺服器程式總不能說掛就掛吧!所以一定要查明真相。

 

1. 跟蹤程式碼查詢到程序退出的源頭

  之前服務端原始碼:https://www.cnblogs.com/songsongman/p/11187844.html

查閱程式碼發現,程式碼主體在while(1)裡面,所以最可疑的地方在於accpet,pthread_create, pthread_join和建立的執行緒client_thread了

明擺著就是client_thread中出了問題,因為accpet,pthread_create, pthread_join中都有根據函式返回值做是否出錯的判斷,還是認慫好好看看執行緒做了什麼:

void *client_thread(void *arg)
{
    int clifd = *(int *)arg;char *s = "hello mysocketclient\n";

    while(1)
    {
        usleep(1000000);
        write(clifd,s,strlen(s));//send(clifd,s,strlen(s),0);
    }

    return (void *)0;
}

哇!居然使用write的時候沒有新增返回值的判斷,在ubuntu終端中輸入man 2 write,可以看到write出錯時候會返回-1;

 

2.簡單完善程式碼容錯機制

新增容錯程式碼後以後看看效果如何,程式碼如下:

    while(1)
    {
        usleep(1000000);
        ret = write(clifd,s,strlen(s));//send(clifd,s,strlen(s),0);
        if(ret == -1)
        {
            printf("client thread write failed !\n");
       close(clifd); pthread_exit(NULL); } }

執行結果如下:

 

過程分析,

1. 先執行服務端程式,然後執行客戶端程式,客戶端程式強制退出(通過快捷鍵ctrl+c),服務端client_thread中write返回-1,執行緒正常退出。

2. 這時候服務端程式還阻塞在accpet等待下一次的客戶端連線請求,執行新的客戶端程式,然後強制退出客戶端,發現服務端程序居然直接退出了!

 

咋辦啊!感覺程式碼沒有任何問題了,為啥還會出錯,雖然很明確一定是write的時候沒能寫進客戶端導致的程序奔潰,但是卻無從下手。

(注意:為了解決這個問題,筆者絞盡腦汁修改,比如新增

shutdown(clifd, SHUT_RDWR);

又或者新增getsockopt來實時獲取連線狀態

)效果都不佳,無法解決問題。

 

3. 新增捕獲異常來再次加強容錯機制

絞盡腦汁似乎沒有什麼效果,抓耳撓腮看看吧,好好翻翻書,看看能不能找到靈感。

從網上找到一本和UNIX系統程式設計有關的書籍《UNIX環境高階程式設計_第二版中文》,因為android是基於linux開發的作業系統,linux又是從UNIX那邊衍射出來的,

所以linux系統程式設計這塊參考這本書特別靠譜。

看到一個和訊號有關的章節,確定了要用signal來檢測異常,可檢測的訊號可真多啊!

                    圖3.1  參考UNIX環境高階程式設計第二版中文第10章表1

             

 然後不小心看到這點

好吧,靈感來了,開始寫程式碼,直接新增標頭檔案

#include <signal.h>

然後再main函式中新增signal(SIGPIPE, SIG_IGN);

執行服務端,再執行客戶端,不管客戶端怎麼退出重啟,服務端都不受影響了。

任務完成!

&n