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

 導讀:html

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

想一想,若是手機上使用一個聊天程序的時候,手機端關閉了聊天程序,那麼遠端服務器程序總不能說掛就掛吧!因此必定要查明真相。android

 

1. 跟蹤代碼查找到進程退出的源頭編程

  以前服務端源碼:http://www.javashuo.com/article/p-uaclxhvz-kv.htmlubuntu

查閱代碼發現,代碼主體在while(1)裏面,因此最可疑的地方在於accpet,pthread_create, pthread_join和建立的線程client_thread了服務器

明擺着就是client_thread中出了問題,由於accpet,pthread_create, pthread_join中都有根據函數返回值作是否出錯的判斷,仍是認慫好好看看線程作了什麼:socket

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.簡單完善代碼容錯機制spa

添加容錯代碼後之後看看效果如何,代碼以下:操作系統

    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);

運行服務端,再運行客戶端,無論客戶端怎麼退出重啓,服務端都不受影響了。

任務完成!

相關文章
相關標籤/搜索