日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux C语言 socket如何判断socket_fd对应的socket是否断开?(是否连通、是否正常连接)recv()、tcp_info TCP_ESTABLISHED、keepalive

發布時間:2025/3/20 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux C语言 socket如何判断socket_fd对应的socket是否断开?(是否连通、是否正常连接)recv()、tcp_info TCP_ESTABLISHED、keepalive 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 判斷socket連接斷開的方法
      • 法一:判斷recv()返回值
        • 但是參考這篇文章的代碼,程序居然被阻塞了,不知道怎么回事
      • 法二:創建tcp_info結構體,判斷info.tcpi_state是否為TCP_ESTABLISHED(注意:需包含tcp.h)
      • 法三:用select函數的方法(沒太看懂)
      • 法四:用keepalive屬性
        • 說明
        • 有關SO_KEEPALIVE的三個參數詳細解釋如下
    • 法五:自己實現心跳檢測

判斷socket連接斷開的方法

法一:判斷recv()返回值

當recv()返回值小于等于0時,socket連接斷開。但是還需要判斷 errno是否等于 EINTR,如果errno == EINTR 則說明recv函數是由于程序接收到信號后返回的,socket連接還是正常的,不應close掉socket連接。

但是參考這篇文章的代碼,程序居然被阻塞了,不知道怎么回事

參考文章:如何在C語言中判斷socket是否已經斷開

#include <errno.h> bool IsSocketClosed(int clientSocket) { char buff[32]; int recvBytes = recv(clientSocket, buff, sizeof(buff), MSG_PEEK); int sockErr = errno; //cout << "In close function, recv " << recvBytes << " bytes, err " << sockErr << endl; if( recvBytes > 0) //Get data return false; if( (recvBytes == -1) && (sockErr == EWOULDBLOCK) ) //No receive data return false; return true; }

法二:創建tcp_info結構體,判斷info.tcpi_state是否為TCP_ESTABLISHED(注意:需包含tcp.h)

struct tcp_info info; int len=sizeof(info); getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); if((info.tcpi_state==TCP_ESTABLISHED)) //則說明未斷開 else 斷開

法三:用select函數的方法(沒太看懂)

若使用了select等系統函數,若遠端斷開,則select返回1,recv返回0則斷開。其他注意事項同法一。

法四:用keepalive屬性

int keepAlive = 1; // 開啟keepalive屬性
int keepIdle = 60; // 如該連接在60秒內沒有任何數據往來,則進行探測
int keepInterval = 5; // 探測時發包的時間間隔為5 秒
int keepCount = 3; // 探測嘗試的次數.如果第1次探測包就收到響應了,則后2次的不再發.

setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void )&keepAlive, sizeof(keepAlive));
setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void)&keepIdle, sizeof(keepIdle));
setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

設置后,若斷開,則在使用該socket讀寫時立即失敗,并返回ETIMEDOUT錯誤

說明

socket心跳機制so_keepalive的三個參數詳解

SO_KEEPALIVE 保持連接檢測對方主機是否崩潰,避免(服務器)永遠阻塞于TCP連接的輸入。

設置該選項后,如果2小時內在此套接口的任一方向都沒有數據交換,TCP就自動給對方 發一個保持存活探測分節(keepalive probe)。這是一個對方必須響應的TCP分節.它會導致以下三種情況:

1、對方接收一切正常:以期望的ACK響應,2小時后,TCP將發出另一個探測分節。

2、對方已崩潰且已重新啟動:以RST響應。套接口的待處理錯誤被置為ECONNRESET,套接 口本身則被關閉。

3、對方無任何響應:源自berkeley的TCP發送另外8個探測分節,相隔75秒一個,試圖得到一個響應。在發出第一個探測分節11分鐘15秒后若仍無響應就放棄。套接口的待處理錯誤被置為ETIMEOUT,套接口本身則被關閉。如ICMP錯誤是“host unreachable(主機不可達)”,說明對方主機并沒有崩潰,但是不可達,這種情況下待處理錯誤被置為 EHOSTUNREACH。

有關SO_KEEPALIVE的三個參數詳細解釋如下

(16)tcp_keepalive_intvl,?;钐綔y消息的發送頻率。默認值為75s。

發送頻率tcp_keepalive_intvl乘以發送次數tcp_keepalive_probes,就得到了從開始探測直到放棄探測確定連接斷開的時間,大約為11min。

(17)tcp_keepalive_probes,TCP發送保活探測消息以確定連接是否已斷開的次數。默認值為9(次)。

注意:只有設置了SO_KEEPALIVE套接口選項后才會發送?;钐綔y消息。

(18)tcp_keepalive_time,在TCP?;畲蜷_的情況下,最后一次數據交換到TCP發送第一個?;钐綔y消息的時間,即允許的持續空閑時間。默認值為7200s(2h)。

法五:自己實現心跳檢測

自己實現一個心跳檢測,一定時間內未收到自定義的心跳包則標記為已斷開。

TCP中已有SO_KEEPALIVE選項,為什么還要在應用層加入心跳包機制?
首先,我想說的是,SO_Keeplive是實現在服務器側,客戶端被動響應,缺省超時時間為120分鐘,這是RFC協議標準規范。

SO_Keeplive是實現在TCP協議棧(四層),應用層的心跳實現在第七層,本質沒有任何區別,但應用層需要自己來定義心跳包格式。

之所以實現在服務器側,是因為與客戶端相比,服務器側的壽命更長,因為服務器側需要不間斷地提供服務,而客戶端可能由于用戶下班而合上電腦(TCP沒有來得及發送FIN關閉連接),這樣的話,服務器側就會有很多不可用的TCP連接(established),這樣的連接依然會占用服務器內存資源,于是就設計這個keepalive 來檢測客戶端是否可用,如果幾次重傳keepalive ,客戶端沒有相應,刪除連接,釋放資源。

需要指出的是,超時時間是指TCP連接沒有任何數據、控制字傳輸的時間,如果有任何數據傳輸,會刷新定時器,重新走表。

TCP心跳是一個備受爭議的實現,只是一個option,不是強制標準。

之所以應用層需要獨立實現自己的心跳,是因為超時時間較長,無法給應用層提供快速的反饋。

所以類似BGP協議就獨立實現了自己的keepalive,最小可以設置一秒鐘,三次沒有應答即可以Reset連接,最快三秒可以檢測到失效。

而三秒依然太慢,可以用另外一個協議BFD來提供更快發現鏈路失效,最快可以配置成10ms
,三次超時(30ms)就可以完成失效檢測。

區別
tcp keepalive檢查連接是否存活。
應用keppalive檢測應用是否正??身憫?。

舉個例子。服務端死鎖,無法處理任何業務請求。但是操作系統仍然可以響應網絡層keepalive包。

參考文章:判斷socket連接斷開的方法

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的linux C语言 socket如何判断socket_fd对应的socket是否断开?(是否连通、是否正常连接)recv()、tcp_info TCP_ESTABLISHED、keepalive的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。