自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么我們要熟悉這些通信協(xié)議?

開發(fā) 前端
在使用某個技術(shù)的時候,一定要去追尋原理和底層的實現(xiàn),長此以往堅持,只要自身底層的基礎(chǔ)扎實,無論技術(shù)怎么變化,學(xué)習(xí)起來都不會太累,總的來說就是拒絕5分鐘技術(shù)。

前端的重要的基礎(chǔ)知識點是什么?

  •  原生javaScript,HTML,CSS.
  •  Dom操作
  •  EventLoop和渲染機制
  •  各類工程化的工具原理以及使用,根據(jù)需求定制編寫插件和包。(webpack的plugin和babel的預(yù)設(shè)包)
  •  數(shù)據(jù)結(jié)構(gòu)和算法(特別是IM以及超大型高并發(fā)網(wǎng)站應(yīng)用等,例如B站)
  •  最后便是通信協(xié)議

在使用某個技術(shù)的時候,一定要去追尋原理和底層的實現(xiàn),長此以往堅持,只要自身底層的基礎(chǔ)扎實,無論技術(shù)怎么變化,學(xué)習(xí)起來都不會太累,總的來說就是拒絕5分鐘技術(shù)。

從輸入一個url地址,到顯示頁面發(fā)生了什么出發(fā):

    1.瀏覽器向 DNS 服務(wù)器請求解析該 URL 中的域名所對應(yīng)的 IP 地址;

    2.建立TCP連接(三次握手);

    3.瀏覽器發(fā)出讀取文件(URL 中域名后面部分對應(yīng)的文件)的HTTP 請求,該請求報文作為 TCP 三次握手的第三個報文的數(shù)據(jù)發(fā)送給服務(wù)器;

    4.服務(wù)器對瀏覽器請求作出響應(yīng),并把對應(yīng)的 html 文本發(fā)送給瀏覽器;

    5.瀏覽器將該 html 文本并顯示內(nèi)容;

    6.釋放 TCP連接(四次揮手)。

目前常見的通信協(xié)議都是建立在TCP鏈接之上

那么什么是TCP呢?

TCP是因特網(wǎng)中的傳輸層協(xié)議,使用三次握手協(xié)議建立連接。當(dāng)主動方發(fā)出SYN連接請求后,等待對方回答。

TCP三次握手的過程如下:

  •  客戶端發(fā)送SYN報文給服務(wù)器端,進(jìn)入SYN_SEND狀態(tài)。
  •  服務(wù)器端收到SYN報文,回應(yīng)一個SYN(SEQ=y)ACK(ACK=x+1)報文,進(jìn)入SYN_RECV狀態(tài)。
  •  客戶端收到服務(wù)器端的SYN報文,回應(yīng)一個ACK(ACK=y+1)報文,進(jìn)入Established狀態(tài)。
  •  三次握手完成,TCP客戶端和服務(wù)器端成功地建立連接,可以開始傳輸數(shù)據(jù)了。

    如圖所示:

TCP的四次揮手:

  •  建立一個連接需要三次握手,而終止一個連接要經(jīng)過四次握手,這是由TCP的半關(guān)閉(half-close)造成的。具體過程如下圖所示。
  •  某個應(yīng)用進(jìn)程首先調(diào)用close,稱該端執(zhí)行“主動關(guān)閉”(active close)。該端的TCP于是發(fā)送一個FIN分節(jié),表示數(shù)據(jù)發(fā)送完畢。
  •  接收到這個FIN的對端執(zhí)行 “被動關(guān)閉”(passive close),這個FIN由TCP確認(rèn)。

注意:FIN的接收也作為一個文件結(jié)束符(end-of-file)傳遞給接收端應(yīng)用進(jìn)程,放在已排隊等候該應(yīng)用進(jìn)程接收的任何其他數(shù)據(jù)之后,因為,F(xiàn)IN的接收意味著接收端應(yīng)用進(jìn)程在相應(yīng)連接上再無額外數(shù)據(jù)可接收。

  •  一段時間后,接收到這個文件結(jié)束符的應(yīng)用進(jìn)程將調(diào)用close關(guān)閉它的套接字。這導(dǎo)致它的TCP也發(fā)送一個FIN。
  •  接收這個最終FIN的原發(fā)送端TCP(即執(zhí)行主動關(guān)閉的那一端)確認(rèn)這個FIN。 [3]

既然每個方向都需要一個FIN和一個ACK,因此通常需要4個分節(jié)。

特別提示: SYN報文用來通知,F(xiàn)IN報文是用來同步的

以上就是面試官常問的三次握手,四次揮手,但是這不僅僅面試題,上面僅僅答到了一點皮毛,學(xué)習(xí)這些是為了讓我們后續(xù)方便了解他的優(yōu)缺點。

在TCP連接建立后,我們可以有多種協(xié)議的方式通信交換數(shù)據(jù):

最古老的方式一:http 1.0

  •  早先1.0的HTTP版本,是一種無狀態(tài)、無連接的應(yīng)用層協(xié)議。
  •  HTTP1.0規(guī)定瀏覽器和服務(wù)器保持短暫的連接,瀏覽器的每次請求都需要與服務(wù)器建立一個TCP連接,服務(wù)器處理完成后立即斷開TCP連接(無連接),服務(wù)器不跟蹤每個客戶端也不記錄過去的請求(無狀態(tài))。
  •  這種無狀態(tài)性可以借助cookie/session機制來做身份認(rèn)證和狀態(tài)記錄。而下面兩個問題就比較麻煩了。
  •  首先,無連接的特性導(dǎo)致最大的性能缺陷就是無法復(fù)用連接。每次發(fā)送請求的時候,都需要進(jìn)行一次TCP的連接,而TCP的連接釋放過程又是比較費事的。這種無連接的特性會使得網(wǎng)絡(luò)的利用率非常低。
  •  其次就是隊頭阻塞(headoflineblocking)。由于HTTP1.0規(guī)定下一個請求必須在前一個請求響應(yīng)到達(dá)之前才能發(fā)送。假設(shè)前一個請求響應(yīng)一直不到達(dá),那么下一個請求就不發(fā)送,同樣的后面的請求也給阻塞了。

Http 1.0的致命缺點就是無法復(fù)用TCP連接和并行發(fā)送請求,這樣每次一個請求都需要三次握手,而且其實建立連接和釋放連接的這個過程是最耗時的,傳輸數(shù)據(jù)相反卻不那么耗時。還有本地時間被修改導(dǎo)致響應(yīng)頭expires的緩存機制失效的問題~(后面會詳細(xì)講)

  •     常見的請求報文~

于是出現(xiàn)了Http 1.1,這也是技術(shù)的發(fā)展必然結(jié)果~

  • Http 1.1出現(xiàn),繼承了Http1.0的優(yōu)點,也克服了它的缺點,出現(xiàn)了keep-alive這個頭部字段,它表示會在建立TCP連接后,完成首次的請求,并不會立刻斷開TCP連接,而是保持這個連接狀態(tài)~進(jìn)而可以復(fù)用這個通道。
  • Http 1.1并且支持請求管道化,“并行”發(fā)送請求,但是這個并行,也不是真正意義上的并行,而是可以讓我們把先進(jìn)先出隊列從客戶端(請求隊列)遷移到服務(wù)端(響應(yīng)隊列)。

例如:客戶端同時發(fā)了兩個請求分別來獲取html和css,假如說服務(wù)器的css資源先準(zhǔn)備就緒,服務(wù)器也會先發(fā)送html再發(fā)送css。

  • B站首頁,就有keep-alive,因為他們也有IM的成分在里面。需要大量復(fù)用TCP連接~

  •  HTTP1.1好像還是無法解決隊頭阻塞的問題

實際上,現(xiàn)階段的瀏覽器廠商采取了另外一種做法,它允許我們打開多個TCP的會話。也就是說,上圖我們看到的并行,其實是不同的TCP連接上的HTTP請求和響應(yīng)。這也就是我們所熟悉的瀏覽器對同域下并行加載6~8個資源的限制。而這,才是真正的并行!

Http 1.1的致命缺點:

 1.明文傳輸。

 2.其實還是沒有解決無狀態(tài)連接的。

 3.當(dāng)有多個請求同時被掛起的時候就會擁塞請求通道,導(dǎo)致后面請求無法發(fā)送。

 4.臃腫的消息首部:HTTP/1.1能壓縮請求內(nèi)容,但是消息首部不能壓縮;在現(xiàn)今請求中,消息首部占請求絕大部分(甚至是全部)也較為常見。

我們也可以用dns-prefetch和 preconnect tcp來優(yōu)化~ 

  1. <link rel="preconnect" href="//example.com" crossorigin>  
  2. <link rel="dns=prefetch" href="//example.com"> 
  • Tip: webpack可以做任何事情,這些都可以用插件實現(xiàn)

基于這些缺點,出現(xiàn)了Http 2.0

相較于HTTP1.1,HTTP2.0的主要優(yōu)點有采用二進(jìn)制幀封裝,傳輸變成多路復(fù)用,流量控制算法優(yōu)化,服務(wù)器端推送,首部壓縮,優(yōu)先級等特點。

HTTP1.x的解析是基于文本的,基于文本協(xié)議的格式解析存在天然缺陷,文本的表現(xiàn)形式有多樣性,要做到健壯性考慮的場景必然很多。而HTTP/2會將所有傳輸?shù)男畔⒎指顬楦〉南⒑蛶?,然后采用二進(jìn)制的格式進(jìn)行編碼,HTTP1.x的頭部信息會被封裝到HEADER frame,而相應(yīng)的RequestBody則封裝到DATAframe里面。不改動HTTP的語義,使用二進(jìn)制編碼,實現(xiàn)方便且健壯。

多路復(fù)用

所有的請求都是通過一個 TCP 連接并發(fā)完成。HTTP/1.x 雖然通過 pipeline 也能并發(fā)請求,但是多個請求之間的響應(yīng)會被阻塞的,所以 pipeline 至今也沒有被普及應(yīng)用,而 HTTP/2 做到了真正的并發(fā)請求。同時,流還支持優(yōu)先級和流量控制。當(dāng)流并發(fā)時,就會涉及到流的優(yōu)先級和依賴。即:HTTP2.0對于同一域名下所有請求都是基于流的,不管對于同一域名訪問多少文件,也只建立一路連接。優(yōu)先級高的流會被優(yōu)先發(fā)送。圖片請求的優(yōu)先級要低于 CSS 和 SCRIPT,這個設(shè)計可以確保重要的東西可以被優(yōu)先加載完。

流量控制

 TCP協(xié)議通過sliding window的算法來做流量控制。發(fā)送方有個sending window,接收方有receive window。http2.0的flow control是類似receive window的做法,數(shù)據(jù)的接收方通過告知對方自己的flow window大小表明自己還能接收多少數(shù)據(jù)。只有Data類型的frame才有flow control的功能。對于flow control,如果接收方在flow window為零的情況下依然更多的frame,則會返回block類型的frame,這張場景一般表明http2.0的部署出了問題。

服務(wù)器端推送

服務(wù)器端的推送,就是服務(wù)器可以對一個客戶端請求發(fā)送多個響應(yīng)。除了對最初請求的響應(yīng)外,服務(wù)器還可以額外向客戶端推送資源,而無需客戶端明確地請求。當(dāng)瀏覽器請求一個html,服務(wù)器其實大概知道你是接下來要請求資源了,而不需要等待瀏覽器得到html后解析頁面再發(fā)送資源請求。

首部壓縮

  •  HTTP 2.0 在客戶端和服務(wù)器端使用“首部表”來跟蹤和存儲之前發(fā)送的鍵-值對,對于相同的數(shù)據(jù),不再通過每次請求和響應(yīng)發(fā)送;通信期間幾乎不會改變的通用鍵-值對(用戶代理、可接受的媒體類型,等等)只需發(fā)送一次。事實上,如果請求中不包含首部(例如對同一資源的輪詢請求),那么 首部開銷就是零字節(jié)。此時所有首部都自動使用之前請求發(fā)送的首部。
  •  如果首部發(fā)生變化了,那么只需要發(fā)送變化了數(shù)據(jù)在Headers幀里面,新增或修改的首部幀會被追加到“首部表”。首部表在 HTTP 2.0 的連接存續(xù)期內(nèi)始終存在,由客戶端和服務(wù)器共同漸進(jìn)地更新 。
  •  本質(zhì)上,當(dāng)然是為了減少請求啦,通過多個js或css合并成一個文件,多張小圖片拼合成Sprite圖,可以讓多個HTTP請求減少為一個,減少額外的協(xié)議開銷,而提升性能。當(dāng)然,一個HTTP的請求的body太大也是不合理的,有個度。文件的合并也會犧牲模塊化和緩存粒度,可以把“穩(wěn)定”的代碼or 小圖 合并為一個文件or一張Sprite,讓其充分地緩存起來,從而區(qū)分開迭代快的文件。

Demo的性能對比:

Http的那些致命缺陷,并沒有完全解決,于是有了https,也是目前應(yīng)用最廣的協(xié)議之一。

HTTP+ 加密 + 認(rèn)證 + 完整性保護(hù) =HTTPS ?

可以這樣認(rèn)為~HTTP 加上加密處理和認(rèn)證以及完整性保護(hù)后即是 HTTPS。

  •  如果在 HTTP 協(xié)議通信過程中使用未經(jīng)加密的明文,比如在 Web 頁面中輸入信用卡號,如果這條通信線路遭到竊聽,那么信用卡號就暴露了。
  •  另外,對于 HTTP 來說,服務(wù)器也好,客戶端也好,都是沒有辦法確認(rèn)通信方的。

因為很有可能并不是和原本預(yù)想的通信方在實際通信。并且還需要考慮到接收到的報文在通信途中已經(jīng)遭到篡改這一可能性。

  • 為了統(tǒng)一解決上述這些問題,需要在 HTTP 上再加入加密處理和認(rèn)證等機制。我們把添加了加密及認(rèn)證機制的 HTTP 稱為 HTTPS。

不加密的重要內(nèi)容被wireshark這類工具抓到包,后果很嚴(yán)重~

HTTPS 是身披 SSL 外殼的 HTTP

HTTPS 并非是應(yīng)用層的一種新協(xié)議。只是 HTTP 通信接口部分用 SSL(SecureSocket Layer)和 TLS(Transport Layer Security)協(xié)議代替而已。

通常,HTTP 直接和 TCP 通信。

  •  當(dāng)使用 SSL 時,則演變成先和 SSL 通信,再由 SSL和 TCP 通信了。簡言之,所謂 HTTPS,其實就是身披 SSL 協(xié)議這層外殼的HTTP。
  •  在采用 SSL 后,HTTP 就擁有了 HTTPS 的加密、證書和完整性保護(hù)這些功能。SSL 是獨立于 HTTP 的協(xié)議,所以不光是 HTTP 協(xié)議,其他運行在應(yīng)用層的 SMTP和 Telnet 等協(xié)議均可配合 SSL 協(xié)議使用??梢哉f SSL 是當(dāng)今世界上應(yīng)用最為廣泛的網(wǎng)絡(luò)安全術(shù)。

相互交換密鑰的公開密鑰加密技術(shù) -----對稱加密

  •  在對 SSL 進(jìn)行講解之前,我們先來了解一下加密方法。SSL 采用一種叫做公開密鑰加密(Public-key cryptography)的加密處理方式。
  •  近代的加密方法中加密算法是公開的,而密鑰卻是保密的。通過這種方式得以保持加密方法的安全性。

加密和解密都會用到密鑰。沒有密鑰就無法對密碼解密,反過來說,任何人只要持有密鑰就能解密了。如果密鑰被攻擊者獲得,那加密也就失去了意義。

HTTPS 采用混合加密機制

  •  HTTPS 采用共享密鑰加密和公開密鑰加密兩者并用的混合加密機制。
  •  但是公開密鑰加密與共享密鑰加密相比,其處理速度要慢。所以應(yīng)充分利用兩者各自的優(yōu)勢,將多種方法組合起來用于通信。在交換密鑰環(huán)節(jié)使用公開密鑰加密方式,之后的建立通信交換報文階段則使用共享密鑰加密方式。

HTTPS雖好,非對稱加密雖好,但是不要濫用

HTTPS 也存在一些問題,那就是當(dāng)使用 SSL 時,它的處理速度會變慢。

SSL 的慢分兩種。一種是指通信慢。另一種是指由于大量消耗 CPU 及內(nèi)存等資源,導(dǎo)致處理速度變慢。

  •  和使用 HTTP 相比,網(wǎng)絡(luò)負(fù)載可能會變慢 2 到 100 倍。除去和 TCP 連接、發(fā)送 HTTP 請求 ? 響應(yīng)以外,還必須進(jìn)行 SSL 通信,因此整體上處理通信量不可避免會增加。
  •  另一點是 SSL 必須進(jìn)行加密處理。在服務(wù)器和客戶端都需要進(jìn)行加密和解密的運算處理。因此從結(jié)果上講,比起 HTTP 會更多地消耗服務(wù)器和客戶端的硬件資源,導(dǎo)致負(fù)載增強。

針對速度變慢這一問題,并沒有根本性的解決方案,我們會使用 SSL 加速器這種(專用服務(wù)器)硬件來改善該問題。該硬件為 SSL 通信專用硬件,相對軟件來講,能夠提高數(shù)倍 SSL 的計算速度。僅在 SSL 處理時發(fā)揮 SSL加速器的功效,以分擔(dān)負(fù)載。

為什么不一直使用 HTTP

  •  既然 HTTPS 那么安全可靠,那為何所有的 Web 網(wǎng)站不一直使用 HTTPS?

其中一個原因是,因為與純文本通信相比,加密通信會消耗更多的 CPU 及內(nèi)存資源。如果每次通信都加密,會消耗相當(dāng)多的資源,平攤到一臺計算機上時,能夠處理的請求數(shù)量必定也會隨之減少。

  •  因此,如果是非敏感信息則使用 HTTP 通信,只有在包含個人信息等敏感數(shù)據(jù)時,才利用 HTTPS 加密通信。

特別是每當(dāng)那些訪問量較多的 Web 網(wǎng)站在進(jìn)行加密處理時,它們所承擔(dān)著的負(fù)載不容小覷。在進(jìn)行加密處理時,并非對所有內(nèi)容都進(jìn)行加密處理,而是僅在那些需要信息隱藏時才會加密,以節(jié)約資源。

  •  除此之外,想要節(jié)約購買證書的開銷也是原因之一。

要進(jìn)行 HTTPS 通信,證書是必不可少的。而使用的證書必須向認(rèn)證機構(gòu)(CA)購買。證書價格可能會根據(jù)不同的認(rèn)證機構(gòu)略有不同。通常,一年的授權(quán)需要數(shù)萬日元(現(xiàn)在一萬日元大約折合 600 人民幣)。那些購買證書并不合算的服務(wù)以及一些個人網(wǎng)站,可能只會選擇采用HTTP 的通信方式。

復(fù)習(xí)完了基本的協(xié)議,介紹下報文格式:

  •  請求報文格式

  •  響應(yīng)報文格式

所謂響應(yīng)頭,請求頭,其實都可以自己添加字段,只要前后端給對應(yīng)的處理機制即可。

Node.js代碼實現(xiàn)響應(yīng)頭的設(shè)置 

  1. if (config.cache.expires) {  
  2.                        res.setHeader("expries", new Date(Date.now() + (config.cache.maxAge * 1000)))  
  3.                    }  
  4.                    if (config.cache.lastModified) {  
  5.                        res.setHeader("last-modified", stat.mtime.toUTCString())  
  6.                    }  
  7.                    if (config.cache.etag) {  
  8.                        res.setHeader('Etag', etagFn(stat))  
  9.                    } 

響應(yīng)頭的詳解:

本人的開源項目,手寫的Node.js靜態(tài)資源服務(wù)器,https://github.com/JinJieTan/...,歡迎 star~

瀏覽器的緩存策略:

  •  首次請求:

  •  非首次請求:

  •  用戶行為與緩存:

不能緩存的請求:

無法被瀏覽器緩存的請求如下:

  •  HTTP信息頭中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或Cache-Control:max-age=0等告訴瀏覽器不用緩存的請求。
  •  需要根據(jù)Cookie,認(rèn)證信息等決定輸入內(nèi)容的動態(tài)請求是不能被緩存的。
  •  經(jīng)過HTTPS安全加密的請求(有人也經(jīng)過測試發(fā)現(xiàn),ie其實在頭部加入Cache-Control:max-age信息,firefox在頭部加入Cache-Control:Public之后,能夠?qū)TTPS的資源進(jìn)行緩寸)。
  •  經(jīng)過HTTPS安全加密的請求(有人也經(jīng)過測試發(fā)現(xiàn),ie其實在頭部加入Cache-Control:max-age信息,firefox在頭部加入Cache-Control:Public之后,能夠?qū)TTPS的資源進(jìn)行緩存,參考《HTTPS的七個誤解》)。
  •  POST請求無法被緩存。
  •  HTTP響應(yīng)頭中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的請求無法被緩存。

即時通訊協(xié)議

從最初的沒有websocket協(xié)議開始:

傳統(tǒng)的協(xié)議無法服務(wù)端主動push數(shù)據(jù),于是有了這些騷操作:

  •  輪詢,在一個定時器中不停向服務(wù)端發(fā)送請求。
  •  長輪詢,發(fā)送請求給服務(wù)端,直到服務(wù)端覺得可以返回數(shù)據(jù)了再返回響應(yīng),否則這個請求一直掛起~
  •  以上兩種都有瑕疵,而且比較明顯,這里不再描述。

為了解決實時通訊,數(shù)據(jù)同步的問題,出現(xiàn)了webSocket。

  •  webSockets的目標(biāo)是在一個單獨的持久連接上提供全雙工、雙向通信。在Javascript創(chuàng)建了Web Socket之后,會有一個HTTP請求發(fā)送到瀏覽器以發(fā)起連接。在取得服務(wù)器響應(yīng)后,建立的連接會將HTTP升級從HTTP協(xié)議交換為WebSocket協(xié)議。
  •  webSocket原理: 在TCP連接第一次握手的時候,升級為ws協(xié)議。后面的數(shù)據(jù)交互都復(fù)用這個TCP通道。
  •  客戶端代碼實現(xiàn): 
  1. const ws = new WebSocket('ws://localhost:8080');  
  2.        ws.onopen = function () {  
  3.            ws.send('123')  
  4.            console.log('open')  
  5.        }  
  6.        ws.onmessage = function () {  
  7.            console.log('onmessage')  
  8.        }  
  9.        ws.onerror = function () {  
  10.            console.log('onerror')  
  11.        }  
  12.        ws.onclose = function () {  
  13.            console.log('onclose')  
  14.        } 
  •  服務(wù)端使用 Node.js語言實現(xiàn) 
  1. const express = require('express')  
  2. const { Server } = require("ws");  
  3. const app = express()  
  4. const wsServer = new Server({ port: 8080 })  
  5. wsServer.on('connection', (ws) => {  
  6.     ws.onopen = function () {  
  7.         console.log('open')  
  8.     }  
  9.     ws.onmessage = function (data) {  
  10.         console.log(data)  
  11.         ws.send('234')  
  12.         console.log('onmessage' + data)  
  13.     }  
  14.     ws.onerror = function () {  
  15.         console.log('onerror')  
  16.     }  
  17.     ws.onclose = function () {  
  18.         console.log('onclose')  
  19.     }  
  20. });  
  21. app.listen(8000, (err) => {  
  22.     if (!err) { console.log('監(jiān)聽OK') } else {  
  23.         console.log('監(jiān)聽失敗')  
  24.     }  
  25. }) 

webSocket的報文格式有一些不一樣:

![圖片上傳中...]

  •  客戶端和服務(wù)端進(jìn)行Websocket消息傳遞是這樣的:
    •   客戶端:將消息切割成多個幀,并發(fā)送給服務(wù)端。
    •   服務(wù)端:接收消息幀,并將關(guān)聯(lián)的幀重新組裝成完整的消息。

即時通訊的心跳檢測:

pingandpong

  •  服務(wù)端Go實現(xiàn): 
  1. package main  
  2. import (  
  3.     "net/http"  
  4.     "time"  
  5.     "github.com/gorilla/websocket"  
  6.  
  7. var (  
  8.     //完成握手操作  
  9.     upgrade = websocket.Upgrader{  
  10.        //允許跨域(一般來講,websocket都是獨立部署的)  
  11.        CheckOrigin:func(r *http.Request) bool {  
  12.             return true  
  13.        },  
  14.     }  
  15.  
  16. func wsHandler(w http.ResponseWriter, r *http.Request) {  
  17.    var (  
  18.          conn *websocket.Conn  
  19.          err error  
  20.          data []byte  
  21.    )  
  22.    //服務(wù)端對客戶端的http請求(升級為websocket協(xié)議)進(jìn)行應(yīng)答,應(yīng)答之后,協(xié)議升級為websocket,http建立連接時的tcp三次握手將保持。  
  23.    if conn, err = upgrade.Upgrade(w, r, nil); err != nil {  
  24.         return  
  25.    }  
  26.     //啟動一個協(xié)程,每隔5s向客戶端發(fā)送一次心跳消息  
  27.     go func() {  
  28.         var (  
  29.             err error  
  30.         )  
  31.         for {  
  32.             if err = conn.WriteMessage(websocket.TextMessage, []byte("heartbeat")); err != nil {  
  33.                 return  
  34.             }  
  35.             time.Sleep(5 * time.Second)  
  36.         }  
  37.     }()  
  38.    //得到websocket的長鏈接之后,就可以對客戶端傳遞的數(shù)據(jù)進(jìn)行操作了  
  39.    for {  
  40.          //通過websocket長鏈接讀到的數(shù)據(jù)可以是text文本數(shù)據(jù),也可以是二進(jìn)制Binary  
  41.         if _, data, err = conn.ReadMessage(); err != nil {  
  42.             goto ERR  
  43.      }  
  44.      if err = conn.WriteMessage(websocket.TextMessage, data); err != nil {  
  45.          goto ERR  
  46.      }  
  47.    }  
  48. ERR:  
  49.     //出錯之后,關(guān)閉socket連接  
  50.     conn.Close()  
  51.  
  52. func main() {  
  53.     http.HandleFunc("/ws", wsHandler)  
  54.     http.ListenAndServe("0.0.0.0:7777", nil)  

客戶端的心跳檢測(Node.js實現(xiàn)): 

  1. this.heartTimer = setInterval(() => {  
  2.       if (this.heartbeatLoss < MAXLOSSTIMES) {  
  3.         events.emit('network', 'sendHeart');  
  4.         this.heartbeatLoss += 1;  
  5.         this.phoneLoss += 1;  
  6.       } else {  
  7.         events.emit('network', 'offline');  
  8.         this.stop();  
  9.       }  
  10.       if (this.phoneLoss > MAXLOSSTIMES) {  
  11.         this.PhoneLive = false 
  12.         events.emit('network', 'phoneDisconnect');  
  13.       }  
  14.     }, 5000); 

自定義即時通信協(xié)議:

從new Socket開始:

  •  目前即時通訊大都使用現(xiàn)有大公司成熟的SDK接入,但是逼格高些還是自己重寫比較好。
  •  打個小廣告,我們公司就是自己定義的即時通訊協(xié)議~招聘一位高級前端,地點深圳-深南大道,做跨平臺IM桌面應(yīng)用開發(fā)的~
  •  客戶端代碼實現(xiàn)(Node.js):
  1. const {Socket} = require('net')   
  2. const tcp = new Socket()  
  3. tcp.setKeepAlive(true);  
  4. tcp.setNoDelay(true);  
  5. //保持底層tcp鏈接不斷,長連接  
  6. 指定對應(yīng)域名端口號鏈接 
  7.  tcp.connect(80,166.166.0.0)  
  8. 建立連接后  
  9. 根據(jù)后端傳送的數(shù)據(jù)類型 使用對應(yīng)不同的解析  
  10. readUInt8 readUInt16LE readUInt32LE readIntLE等處理后得到myBuf   
  11. const myBuf = buffer.slice(start);//從對應(yīng)的指針開始的位置截取buffer  
  12. const header = myBuf.slice(headstart,headend)//截取對應(yīng)的頭部buffer  
  13. const body = JSON.parse(myBuf.slice(headend-headstart,bodylength).tostring())  
  14. //精確截取數(shù)據(jù)體的buffer,并且轉(zhuǎn)化成js對象 

即時通訊強烈推薦使用Golang,GRPC,Prob傳輸數(shù)據(jù)。

上面的一些代碼,都在我的開源項目中:

  •  手寫的靜態(tài)資源服務(wù)器,https://github.com/JinJieTan/...
  •  webpack-electron-react-websocket的Demo, https://github.com/JinJieTan/...

覺得寫得不錯,可以點個贊支持下,文章也借鑒了一下其他大佬的文章,但是地址都貼上來了~ 歡迎gitHub點個star哦~  

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2023-10-12 19:37:50

通信協(xié)議HTTP

2021-12-05 23:14:24

微服務(wù)GolanggRPC

2024-01-23 12:47:27

2022-12-02 14:42:37

2010-06-11 14:31:08

通信協(xié)議

2017-04-05 16:40:45

2010-07-06 17:14:03

網(wǎng)關(guān)通信協(xié)議

2019-05-27 06:05:20

物聯(lián)網(wǎng)協(xié)議物聯(lián)網(wǎng)IOT

2010-06-11 14:25:08

通信協(xié)議

2010-06-25 14:43:46

通信協(xié)議

2021-01-26 05:37:08

分庫分表內(nèi)存

2014-05-30 15:56:26

iOS 8WWDC2014

2010-11-03 09:22:00

C語言

2021-05-17 08:20:22

職場晉升轉(zhuǎn)型

2010-06-09 10:43:54

廣義網(wǎng)協(xié)議

2019-08-23 12:49:18

USB通信協(xié)議

2019-04-29 10:26:49

TCP網(wǎng)絡(luò)協(xié)議網(wǎng)絡(luò)通信

2009-12-22 09:37:47

網(wǎng)關(guān)設(shè)置通信協(xié)議

2015-02-26 09:41:50

2016-08-22 13:31:05

前端架構(gòu)前后端分離
點贊
收藏

51CTO技術(shù)棧公眾號