Linux下send函數 Broken pipe錯誤的解決方法


在linux下寫socket的程序的時候,如果嘗試send到一個disconnected socket上,就會讓底層拋出一個SIGPIPE信號。

client端通過 pipe 發送信息到server端后,就關閉client端, 這時server端,返回信息給 client 端時就產生Broken pipe 信號了。

對於產生信號,我們可以在產生信號前利用方法 signal(int signum, sighandler_t handler) 設置信號的處理。如果沒有調用此方法,系統就會調用默認處理方法:中止程序,顯示提示信息(就是我們經常遇到的問題)。我們可以調用系統的處理方法,也可以自定義處理方法。

對一個已經收到FIN包的socket調用read方法, 如果接收緩沖已空, 則返回0,
這就是常說的表示連接關閉. 但第一次對其調用write方法時, 如果發送緩沖沒問題,
會返回正確寫入(發送). 但發送的報文會導致對端發送RST報文,
因為對端的socket已經調用了close, 完全關閉, 既不發送, 也不接收數據. 所以,
第二次調用write方法(假設在收到RST之后), 會生成SIGPIPE信號, 導致進程退出.

為了避免進程退出, 可以捕獲SIGPIPE信號, 或者忽略它,
給它設置SIG_IGN信號處理函數:

signal(SIGPIPE, SIG_IGN);

這樣, 第二次調用write方法時, 會返回-1, 同時errno置為SIGPIPE.
程序便能知道對端已經關閉.

PS: Linux下的SIGALRM似乎會每1秒鍾往后偏移1毫秒,
但Windows下經過測試完全准時, 不差1毫秒.

頭文件 #include <signal.h>

struct sigaction sa;
sa.sa_handler = SIG_IGN;//設定接受到指定信號后的動作為忽略
sa.sa_flags = 0;
if (sigemptyset(&sa.sa_mask) == -1 || //初始化信號集為空
sigaction(SIGPIPE, &sa, 0) == -1) { //屏蔽SIGPIPE信號
perror("failed to ignore SIGPIPE; sigaction");
exit(EXIT_FAILURE);
}

pthread線程里如何屏蔽SIGPIPE異常
在pthread中,可能會遇到Program received signal SIGPIPE, Broken
pipe的問題,解決方法是每一個線程啟動之前時,先執行下面代碼:

#ifndef WIN32
sigset_t signal_mask;
sigemptyset (&signal_mask);
sigaddset (&signal_mask, SIGPIPE);
int rc = pthread_sigmask (SIG_BLOCK, &signal_mask, NULL);
if (rc != 0) {
printf("block sigpipe error\n");
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM