php websocket 是否在线_看完让你彻底理解WebSocket原理,附实战代码(包含前端和后端)...
1、前言
最近有同學(xué)問我有沒有做過在線咨詢功能。同時(shí),公司也剛好讓我接手一個(gè) IM 項(xiàng)目。所以今天抽時(shí)間記錄一下最近學(xué)習(xí)的內(nèi)容。本文主要剖析了 WebSocket 的原理,以及附上一個(gè)完整的聊天室實(shí)戰(zhàn) Demo (包含前端和后端,代碼下載鏈接在文末)。
2、WebSocket 與 HTTP
WebSocket 協(xié)議在2008年誕生,2011年成為國際標(biāo)準(zhǔn)。現(xiàn)在所有瀏覽器都已經(jīng)支持了。WebSocket 的最大特點(diǎn)就是,服務(wù)器可以主動(dòng)向客戶端推送信息,客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息,是真正的雙向平等對(duì)話。
HTTP 有 1.1 和 1.0 之說,也就是所謂的 keep-alive ,把多個(gè) HTTP 請(qǐng)求合并為一個(gè),但是 Websocket 其實(shí)是一個(gè)新協(xié)議,跟 HTTP 協(xié)議基本沒有關(guān)系,只是為了兼容現(xiàn)有瀏覽器,所以在握手階段使用了 HTTP 。
下面一張圖說明了 HTTP 與 WebSocket 的主要區(qū)別:
WebSocket 的其他特點(diǎn):
- 建立在 TCP 協(xié)議之上,服務(wù)器端的實(shí)現(xiàn)比較容易。
- 與 HTTP 協(xié)議有著良好的兼容性。默認(rèn)端口也是80和443,并且握手階段采用 HTTP 協(xié)議,因此握手時(shí)不容易屏蔽,能通過各種 HTTP 代理服務(wù)器。
- 數(shù)據(jù)格式比較輕量,性能開銷小,通信高效。
- 可以發(fā)送文本,也可以發(fā)送二進(jìn)制數(shù)據(jù)。
- 沒有同源限制,客戶端可以與任意服務(wù)器通信。
- 協(xié)議標(biāo)識(shí)符是ws(如果加密,則為wss),服務(wù)器網(wǎng)址就是 URL。
3、WebSocket 是什么樣的協(xié)議,具體有什么優(yōu)點(diǎn)
首先,WebSocket 是一個(gè)持久化的協(xié)議,相對(duì)于 HTTP 這種非持久的協(xié)議來說。簡單的舉個(gè)例子吧,用目前應(yīng)用比較廣泛的 PHP 生命周期來解釋。
HTTP 的生命周期通過 Request 來界定,也就是一個(gè) Request 一個(gè) Response ,那么在 HTTP1.0 中,這次 HTTP 請(qǐng)求就結(jié)束了。
在 HTTP1.1 中進(jìn)行了改進(jìn),使得有一個(gè) keep-alive,也就是說,在一個(gè) HTTP 連接中,可以發(fā)送多個(gè) Request,接收多個(gè) Response。但是請(qǐng)記住 Request = Response, 在 HTTP 中永遠(yuǎn)是這樣,也就是說一個(gè) Request 只能有一個(gè) Response。而且這個(gè) Response 也是被動(dòng)的,不能主動(dòng)發(fā)起。
你 BB 了這么多,跟 WebSocket 有什么關(guān)系呢?好吧,我正準(zhǔn)備說 WebSocket 呢。
首先 WebSocket 是基于 HTTP 協(xié)議的,或者說借用了 HTTP 協(xié)議來完成一部分握手。
首先我們來看個(gè)典型的 WebSocket 握手
GET /chat HTTP/1.1Host: server.example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13Origin: http://example.com熟悉 HTTP 的童鞋可能發(fā)現(xiàn)了,這段類似 HTTP 協(xié)議的握手請(qǐng)求中,多了這么幾個(gè)東西。
Upgrade: websocketConnection: Upgrade這個(gè)就是 WebSocket 的核心了,告訴 Apache 、 Nginx 等服務(wù)器:注意啦,我發(fā)起的請(qǐng)求要用 WebSocket 協(xié)議,快點(diǎn)幫我找到對(duì)應(yīng)的助理處理~而不是那個(gè)老土的 HTTP。
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13首先, Sec-WebSocket-Key 是一個(gè) Base64 encode 的值,這個(gè)是瀏覽器隨機(jī)生成的,告訴服務(wù)器:泥煤,不要忽悠我,我要驗(yàn)證你是不是真的是 WebSocket 助理。
然后, Sec_WebSocket-Protocol 是一個(gè)用戶定義的字符串,用來區(qū)分同 URL 下,不同的服務(wù)所需要的協(xié)議。簡單理解:今晚我要服務(wù)A,別搞錯(cuò)啦~
最后, Sec-WebSocket-Version 是告訴服務(wù)器所使用的 WebSocket Draft (協(xié)議版本),在最初的時(shí)候,WebSocket 協(xié)議還在 Draft 階段,各種奇奇怪怪的協(xié)議都有,而且還有很多期奇奇怪怪不同的東西,什么 Firefox 和 Chrome 用的不是一個(gè)版本之類的,當(dāng)初 WebSocket 協(xié)議太多可是一個(gè)大難題。。不過現(xiàn)在還好,已經(jīng)定下來啦~大家都使用同一個(gè)版本:服務(wù)員,我要的是.....→_→
然后服務(wù)器會(huì)返回下列東西,表示已經(jīng)接受到請(qǐng)求, 成功建立 WebSocket 啦!
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=Sec-WebSocket-Protocol: chat這里開始就是 HTTP 最后負(fù)責(zé)的區(qū)域了,告訴客戶,我已經(jīng)成功切換協(xié)議啦~
Upgrade: websocketConnection: Upgrade依然是固定的,告訴客戶端即將升級(jí)的是 WebSocket 協(xié)議,而不是 mozillasocket,lurnarsocket 或者 shitsocket。
然后, Sec-WebSocket-Accept 這個(gè)則是經(jīng)過服務(wù)器確認(rèn),并且加密過后的 Sec-WebSocket-Key 。服務(wù)器:好啦好啦,知道啦,給你看我的 ID CARD 來證明行了吧。
后面的, Sec-WebSocket-Protocol 則是表示最終使用的協(xié)議。
至此,HTTP 已經(jīng)完成它所有工作了,接下來就是完全按照 WebSocket 協(xié)議進(jìn)行了。
4、WebSocket 的作用
在講 WebSocket之前,我就順帶著講下 ajax輪詢 和 long poll 的原理。
4-1、ajax輪詢
ajax輪詢的原理非常簡單,讓瀏覽器隔個(gè)幾秒就發(fā)送一次請(qǐng)求,詢問服務(wù)器是否有新信息。
場(chǎng)景再現(xiàn):
客戶端:啦啦啦,有沒有新信息(Request)服務(wù)端:沒有(Response)客戶端:啦啦啦,有沒有新信息(Request)服務(wù)端:沒有。。(Response)客戶端:啦啦啦,有沒有新信息(Request)服務(wù)端:你好煩啊,沒有啊。。(Response)客戶端:啦啦啦,有沒有新消息(Request)服務(wù)端:好啦好啦,有啦給你。(Response)客戶端:啦啦啦,有沒有新消息(Request)服務(wù)端:。。。。。沒。。。。沒。。。沒有(Response) —- loop4-2、long poll
long poll 其實(shí)原理跟 ajax輪詢 差不多,都是采用輪詢的方式,不過采取的是阻塞模型(一直打電話,沒收到就不掛電話),也就是說,客戶端發(fā)起請(qǐng)求后,如果沒消息,就一直不返回 Response 給客戶端。直到有消息才返回,返回完之后,客戶端再次建立連接,周而復(fù)始。
場(chǎng)景再現(xiàn):
客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request)服務(wù)端:額。。等待到有消息的時(shí)候。。來 給你(Response)客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request) -loop從上面可以看出其實(shí)這兩種方式,都是在不斷地建立HTTP連接,然后等待服務(wù)端處理,可以體現(xiàn)HTTP協(xié)議的另外一個(gè)特點(diǎn),被動(dòng)性。
何為被動(dòng)性呢,其實(shí)就是,服務(wù)端不能主動(dòng)聯(lián)系客戶端,只能有客戶端發(fā)起。
從上面很容易看出來,不管怎么樣,上面這兩種都是非常消耗資源的。
ajax輪詢 需要服務(wù)器有很快的處理速度和資源。long poll 需要有很高的并發(fā),也就是說同時(shí)接待客戶的能力。
所以 ajax輪詢 和 long poll 都有可能發(fā)生這種情況。
客戶端:啦啦啦啦,有新信息么?服務(wù)端:正忙,請(qǐng)稍后再試(503 Server Unavailable)客戶端:。。。。好吧,啦啦啦,有新信息么?服務(wù)端:正忙,請(qǐng)稍后再試(503 Server Unavailable)4-3、WebSocket
通過上面這兩個(gè)例子,我們可以看出,這兩種方式都不是最好的方式,需要很多資源。
一種需要更快的速度,一種需要更多的’電話’。這兩種都會(huì)導(dǎo)致’電話’的需求越來越高。
哦對(duì)了,忘記說了 HTTP 還是一個(gè)無狀態(tài)協(xié)議。通俗的說就是,服務(wù)器因?yàn)槊刻煲哟嗫蛻袅?#xff0c;是個(gè)健忘鬼,你一掛電話,他就把你的東西全忘光了,把你的東西全丟掉了。你第二次還得再告訴服務(wù)器一遍。
所以在這種情況下出現(xiàn)了 WebSocket 。他解決了 HTTP 的這幾個(gè)難題。首先,被動(dòng)性,當(dāng)服務(wù)器完成協(xié)議升級(jí)后(HTTP->Websocket),服務(wù)端就可以主動(dòng)推送信息給客戶端啦。所以上面的情景可以做如下修改。
客戶端:啦啦啦,我要建立Websocket協(xié)議,需要的服務(wù):chat,Websocket協(xié)議版本:17(HTTP Request)服務(wù)端:ok,確認(rèn),已升級(jí)為Websocket協(xié)議(HTTP Protocols Switched)客戶端:麻煩你有信息的時(shí)候推送給我噢。。服務(wù)端:ok,有的時(shí)候會(huì)告訴你的。服務(wù)端:balabalabalabala服務(wù)端:balabalabalabala服務(wù)端:哈哈哈哈哈啊哈哈哈哈服務(wù)端:笑死我了哈哈哈哈哈哈哈這樣,只需要經(jīng)過一次 HTTP 請(qǐng)求,就可以做到源源不斷的信息傳送了。
5、實(shí)戰(zhàn)代碼
參考文檔:
php socket 文檔:https://php.net/manual/zh/ref.sockets.phpjs 的 WebSocket 文檔:https://developer.mozilla.org/en-US/docs/Web/API/WebSocket前端代碼:
https://github.com/nnngu/WebSocketDemo-js
后端代碼:
https://github.com/nnngu/WebSocketDemo-php
運(yùn)行步驟:
- 在終端打開 WebSocketDemo-php 目錄,執(zhí)行 php -q server.php
- 用瀏覽器訪問 WebSocketDemo-js 目錄里面的 index.html
運(yùn)行截圖:
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的php websocket 是否在线_看完让你彻底理解WebSocket原理,附实战代码(包含前端和后端)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 报告:2022 年非法使用加密货币的金额
- 下一篇: phpfpm内存越来越高_硬件集成度越来