socket 斷線重連和心跳機(jī)制如何實(shí)現(xiàn)?

一、socket 概念

1.套接字(socket)是網(wǎng)絡(luò)通信的基石,是支持 TCP/IP 協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。它是網(wǎng)絡(luò)通信過(guò)程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的 IP 地址,本地進(jìn)程的通信端口,遠(yuǎn)程主機(jī)的 IP 地址,遠(yuǎn)程進(jìn)程的通信端口。

2.為了區(qū)別不同的應(yīng)用程序進(jìn)程和連接,許多計(jì)算機(jī)操作系統(tǒng)為應(yīng)用程序與 TCP/IP 協(xié)議交互提供了套接字(socket)接口進(jìn)行編程。

3.應(yīng)用層和傳輸層可以通過(guò) socket 接口,區(qū)分來(lái)自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實(shí)現(xiàn)數(shù)據(jù)通信的并發(fā)服務(wù)。

二、建立 socket 連接

1.建立 socket 連接至少需要一對(duì)套接字,其中一個(gè)運(yùn)行于客戶(hù)端,稱(chēng)為 ClientSocket ,另一個(gè)運(yùn)行于服務(wù)端,稱(chēng)為 ServerSocket 。

2.套接字之間的連接過(guò)程分為三個(gè)步驟:服務(wù)端監(jiān)聽(tīng),客戶(hù)端請(qǐng)求,連接確認(rèn)。

1)服務(wù)端監(jiān)聽(tīng)

服務(wù)端套接字并不僅限于具體的客戶(hù)端套接字,而是處于等待連接的狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶(hù)端的連接請(qǐng)求。

2)客戶(hù)端請(qǐng)求

客戶(hù)端的套接字向要連接的目標(biāo)服務(wù)端的套接字提出連接請(qǐng)求。

為此,客戶(hù)端的套接字必須首先描述它要連接的服務(wù)端的套接字,指出服務(wù)端套接字的地址和端口號(hào),然后就可以向服務(wù)端套接字提出連接請(qǐng)求。

3)連接確認(rèn)

當(dāng)服務(wù)端套接字監(jiān)聽(tīng)到或者接收到客戶(hù)端套接字的連接請(qǐng)求時(shí),就會(huì)去響應(yīng)客戶(hù)端套接字的請(qǐng)求,建立一個(gè)新的線程,把服務(wù)端套接字的描述發(fā) 給客戶(hù)端,一旦客戶(hù)端確認(rèn)了此描述,雙方就正式建立連接。

此外,服務(wù)端套接字繼續(xù)處于監(jiān)聽(tīng)狀態(tài),繼續(xù)接收其他客戶(hù)端套接字的連接請(qǐng)求。

3.socket 連接與 HTTP 連接

1)創(chuàng)建 socket 連接時(shí),可以指定使用某個(gè)傳輸層協(xié)議,socket 支持不同的傳輸層協(xié)議(TCP(Transmission Control Protocol)或 UDP(User Datagram Protocol))。

當(dāng)使用 TCP 協(xié)議進(jìn)行連接時(shí),該 socket 連接就是一個(gè) TCP 連接。

2)socket 連接

通常情況下 socket 連接就是 TCP 連接,因此 socket 連接一旦建立,通信雙方即可開(kāi)始互相發(fā)送數(shù)據(jù)內(nèi)容,直到雙方連接斷開(kāi)。

但在實(shí)際網(wǎng) 絡(luò)應(yīng)用中,客戶(hù)端與服務(wù)端之間的通信往往需要穿越多個(gè)中間節(jié)點(diǎn),例如路由器、網(wǎng)關(guān)、防火墻等。大部分防火墻默認(rèn)會(huì)關(guān)閉長(zhǎng)時(shí)間處于非活躍狀態(tài)的連接而導(dǎo)致 socket 連接斷連,因此需要通過(guò)輪詢(xún)告訴網(wǎng)絡(luò),該連接處于活躍狀態(tài)。

3)HTTP連接 HTTP連接使用的是"請(qǐng)求—響應(yīng)"的方式,不僅在請(qǐng)求時(shí)需要先建立連接,而且需要客戶(hù)端向服務(wù)端發(fā)出請(qǐng)求后,服務(wù)端才能返回?cái)?shù)據(jù)。

很多情況下,需要服務(wù)端主動(dòng)向客戶(hù)端推送數(shù)據(jù),保持客戶(hù)端與服務(wù)端數(shù)據(jù)的實(shí)時(shí)與同步。

此時(shí)若雙方建立的是 socket 連接,服務(wù)端就可以直接將數(shù) 據(jù)傳送給客戶(hù)端。

若雙方建立的是 HTTP 連接,則服務(wù)端需要等到客戶(hù)端發(fā)送一次請(qǐng)求后才能將數(shù)據(jù)返回給客戶(hù)端。

因此,客戶(hù)端定時(shí)向服務(wù)端發(fā)送連接請(qǐng)求,不僅可以保持在線,同時(shí)也是在"詢(xún)問(wèn)"服務(wù)端是否有新的數(shù)據(jù),如果有就將數(shù)據(jù)傳給客戶(hù)端。

備注:(在HTTP/2及以上版本里,已經(jīng)可以實(shí)現(xiàn)服務(wù)端向客戶(hù)端主動(dòng)發(fā)送數(shù)據(jù)的邏輯。)

三、socket斷線重連和心跳機(jī)制

1.socket 斷線重連實(shí)現(xiàn)

1)正常連接斷開(kāi)時(shí)客戶(hù)端會(huì)給服務(wù)端發(fā)送一個(gè) fin 包,服務(wù)端收到 fin 包后才會(huì)知道連接準(zhǔn)備斷開(kāi)。

2)而斷網(wǎng)斷電時(shí)客戶(hù)端無(wú)法發(fā)送 fin 包給服務(wù)端,所以服務(wù)端就沒(méi)辦法檢測(cè)到客戶(hù)端是否已經(jīng)斷線。

3)為了解決這個(gè)問(wèn)題,服務(wù)端需要有個(gè)心跳邏輯,就是服務(wù)端檢測(cè)到某個(gè)客戶(hù)端多久沒(méi)發(fā)送任何數(shù)據(jù)過(guò)來(lái)就認(rèn)為客戶(hù)端已經(jīng)斷開(kāi), 這需要客戶(hù)端定時(shí)向服務(wù)端發(fā)送心跳數(shù)據(jù)維持連接。

2.socket心跳機(jī)制實(shí)現(xiàn)

1)長(zhǎng)連接的實(shí)現(xiàn)

心跳機(jī)制,應(yīng)用層協(xié)議大多都有 HeartBeat(心跳) 機(jī)制,通常是客戶(hù)端每隔一小

段時(shí)間向服務(wù)端發(fā)送一個(gè)數(shù)據(jù)包,通知服務(wù)端自己仍然在線,并傳輸一些可能必要的數(shù)據(jù)。

使用心跳包的典型協(xié)議是 IM(Instant Messaging,即時(shí)通信),比如 微信/QQ/MSN/飛信等應(yīng)用。

2)在 TCP 傳輸層協(xié)議 的機(jī)制里面,本身也是存在心跳包機(jī)制的,那就是 TCP 的選項(xiàng):SO_KEEPALIVE。

系統(tǒng)默認(rèn)設(shè)置的是 2 小時(shí)的心跳頻率。但是它檢查不到機(jī)器斷電、網(wǎng)線拔出、防火墻這些斷線。

邏輯層處理斷線可能也不是那么好處理。一般,如果只是用于保活還是可以的。

通過(guò)使用 TCP 的 KeepAlive 機(jī)制(修改 SO_KEEPALIVE參數(shù)),可以讓連接每隔一小段時(shí)間就產(chǎn)生一些 ack 包,以降低被服務(wù)端斷開(kāi)的風(fēng)險(xiǎn)。當(dāng)然,這樣的代價(jià)是額外的網(wǎng)絡(luò)和 CPU 負(fù)擔(dān)。

四、應(yīng)用層心跳機(jī)制實(shí)現(xiàn)

1.定義心跳包的格式和大小。

2.在客戶(hù)端和服務(wù)端分別設(shè)置定時(shí)器(一般幾秒到幾十秒之間),用于定時(shí)發(fā)送心跳包。

3.定時(shí)器觸發(fā),由客戶(hù)端或服務(wù)端發(fā)送心跳包給到對(duì)端。

4.接收方收到心跳包后,應(yīng)立即發(fā)送一個(gè)響應(yīng)包給發(fā)送端,以確保連接仍然活躍。

5.若發(fā)送方在一定時(shí)間內(nèi)未收到響應(yīng)包,則認(rèn)為連接已經(jīng)斷開(kāi)或?qū)Ψ綗o(wú)響應(yīng)。此時(shí)需要進(jìn)行處理,如重建連接、記錄日志、通知用戶(hù)等。








微風(fēng)不燥,陽(yáng)光正好,你就像風(fēng)一樣經(jīng)過(guò)這里,愿你停留的片刻溫暖舒心。

我是程序員小迷(致力于C、C++、Java、Kotlin、Android、iOS、Shell、JavaScript、TypeScript、Python等編程技術(shù)的技巧經(jīng)驗(yàn)分享),若作品對(duì)您有幫助,請(qǐng)關(guān)注、分享、點(diǎn)贊、收藏、在看、喜歡,您的支持是我們?yōu)槟峁椭淖畲髣?dòng)力。

歡迎關(guān)注。助您在編程路上越走越好!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容