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