文章目錄1.websocket的由來??我們經(jīng)常用的是HTTP協(xié)議,而HTTP協(xié)議是一種無狀態(tài)的協(xié)議,要實(shí)現(xiàn)有狀態(tài)的會話必須借助一些外部機(jī)制如session和cookie,這或多或少會帶來一些不便,尤其是服務(wù)端和客戶端需要實(shí)時交換數(shù)據(jù)的時候(監(jiān)控,聊天),這個問題更加明顯。為了適應(yīng)這種環(huán)境,websocket就產(chǎn)生了。
2.什么是websocket??是一種在單個TCP連接上進(jìn)行全雙工通信的持久化協(xié)議。
3.websocket的特點(diǎn)或作用允許服務(wù)端主動向客戶端推送數(shù)據(jù)(允許服務(wù)端主動向客戶端推送數(shù)據(jù)) 在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。
4.應(yīng)用的場景聊天:比如我們常用的兩天軟件,就用到了websocket 監(jiān)控:實(shí)時監(jiān)控一個網(wǎng)站的在線
總之適用于:客戶端與服務(wù)器段高頻率低延遲交換事件。
5.使用websocket的優(yōu)點(diǎn)更強(qiáng)的實(shí)時性 保持連接狀態(tài),創(chuàng)建一次連接后,之后通信時可以省略部分狀態(tài)信息 較少的控制開銷,在連接創(chuàng)建后,服務(wù)器和客戶端之間交換數(shù)據(jù)時,用于協(xié)議控制的數(shù)據(jù)包頭部相對較小。在不包含擴(kuò)展的情況下,對于服務(wù)器到客戶端的內(nèi)容,此頭部大小只有2至10字節(jié)(和數(shù)據(jù)包長度有關(guān));對于客戶端到服務(wù)器的內(nèi)容,此頭部還需要加上額外的4字節(jié)的掩碼。相對于HTTP請求每次都要攜帶完整的頭部,此項(xiàng)開銷顯著減少了
6.使用websocket的缺點(diǎn)由于websocket使用的持久連接,與服務(wù)器一直保持連接,對服務(wù)器壓力很大
7.websocket 的通信過程??只需建立一次Request/Response消息對,之后都是TCP連接,避免了需要多次建立Request/Response消息對而產(chǎn)生的冗余頭部信息。Request/Response需要三次w
8.如何用websocket
瀏覽器發(fā)送websocket請求頭類似如下:
 下面是對請求頭部解釋(比http協(xié)議多了Upgrade和Connection,是告訴服務(wù)器包協(xié)議設(shè)計(jì)為ws): Accept-Encoding:瀏覽器可以接受的數(shù)據(jù)的壓縮類型。 Accept-Language:瀏覽器可以接受的語言類型。 Cache-Control:no-cache不使用強(qiáng)緩存。 Connection:Upgrade 通知服務(wù)器通信協(xié)議提升。 Host:主機(jī)名。 Origin:用于驗(yàn)證瀏覽器域名是否在服務(wù)器許可范圍內(nèi)。 Pragma:no-cache HTTP/1.0定義的不使用本地緩存。 Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits Sec-WebSocket-Key:lb69kw8CsB4CrSk9tKa3 g== 握手協(xié)議密鑰,base64編碼的16字節(jié)的隨機(jī)字符串。 Sec-WebSocket-Version:13 版本號。 Upgrade:websocket 使用websocket協(xié)議進(jìn)行傳輸數(shù)據(jù),而不使用HTTP/1.1。 User-Agent:用戶代理字符串。
服務(wù)器接收到客戶端請求后做出響應(yīng)并返回如下:
 下面是服務(wù)器返回的頭部解釋: Connection:Upgrade 通信協(xié)議提升。 Date:通信時間 Upgrade: websocket 傳輸協(xié)議升級為websocket。 Sec-WebSocket-Extensions:permessage-deflate Sec-WebSocket-Accept:q9g5u1WfIWaAjNgMmjlTQTqkS/k= 將Sec-WebSocket-Key的值進(jìn)行一定的運(yùn)算和該值進(jìn)行比較來判斷是否是目標(biāo)服務(wù)器響應(yīng)了WebSocket請求。 Upgrade: 使用websocket協(xié)議進(jìn)行數(shù)據(jù)傳輸
8.1 客戶端如何用websocket這里我所指的客戶端通常是指瀏覽器,而且都支持WebSocket API。你也可以通過window.WebSocket來判斷你的瀏覽器是否支持WebSocket, var ws = null;
function connect(){
// 1. 創(chuàng)建websocket實(shí)例
if ('WebSocket' in window){
ws = new WebSocket("ws://127.0.0.1:8086/socketServer/" $("#username").val());
}
else if ('MozWebSocket' in window){
ws = new MozWebSocket("ws://127.0.0.1:8086/socketServer/" $("#username").val());
}
else{
alert("該瀏覽器不支持websocket");
}
// 2. 新建session,即創(chuàng)建連接時觸發(fā)此方法
ws.onopen = function() {
// 可以在此寫創(chuàng)建會話后想實(shí)現(xiàn)的的邏輯
};
// 3. 接受消息,evt 是接收到服務(wù)端返回給客戶端的數(shù)據(jù)
ws.onmessage = function(evt) {
// 可以在接受消息后想實(shí)現(xiàn)的的邏輯,比如修改頁面上顯示在線認(rèn)數(shù)
};
// 4. 關(guān)閉連接
ws.onclose = function() {
// 可以在此寫會話關(guān)閉后想實(shí)現(xiàn)的的邏輯
};
// 5. 出現(xiàn)錯誤
ws.onerror = function (e) {
// 可以在此寫出現(xiàn)錯誤后想實(shí)現(xiàn)的的邏輯
};
}
// 客戶端給服務(wù)端發(fā)送消息時,調(diào)用此方法
function sendMsg() {
// 調(diào)用ws的send()事件
ws.send(發(fā)送的內(nèi)容);
}
解釋: 首先要創(chuàng)建webSocket的實(shí)例,url一定是ws形式 然后給ws綁定open,message,error,close四個事件 發(fā)送數(shù)據(jù)使用send方法,該方法除了可以發(fā)送字符串以外還可以發(fā)送blob和二進(jìn)制數(shù)據(jù) 創(chuàng)建好的ws對象有一個readyState屬性,它的取值有0,1,2,3分別表示正在連接,連接成功,正在關(guān)閉,連接關(guān)閉
8.2 服務(wù)端如何用websocket(以springboot項(xiàng)目為例)第一步:引依賴 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<-- 使用springboot的內(nèi)置tomcat時,就不需要引入javaEE-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
第二步:啟用websocket的支持 import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
第三步:通信的具體實(shí)現(xiàn): 具體實(shí)現(xiàn)可以參照如下例子,實(shí)現(xiàn)了一個簡單的聊天功能:鏈接:https://pan.baidu.com/s/1iTjETNwQrICfHyDDh5yicg 提取碼:0el5 ,可以參考下面這篇博客:https://blog.csdn.net/moshowgame/article/details/80275084
簡單說一下聊天實(shí)現(xiàn)的邏輯:每次客戶端創(chuàng)建連接時會產(chǎn)生一個會話session,并存放起來,該session唯一標(biāo)識,當(dāng)客戶端發(fā)送消息時,會給服務(wù)端發(fā)送包含發(fā)送給誰及發(fā)送內(nèi)容的信息的消息message,然后客戶端根據(jù)客戶端傳過來的發(fā)送給誰的信息查詢對應(yīng)的session,然后調(diào)用session.getBasicRemote().sendText(message)就可以給對方發(fā)送消息了,對方會監(jiān)聽ws.onmessage()方法,該方法就是監(jiān)聽對方發(fā)消息的,只要對方發(fā)消息就會觸發(fā)該方法然后接受消息,如果時群發(fā),循環(huán)調(diào)用上面的步驟即可
9.http 與 websocket 的區(qū)別??三次握手詳解參見:https://www.jianshu.com/p/85aef5a0e3d8, ??四次揮手詳解參見:https://www.cnblogs.com/qdhxhz/p/8470997.html 9.1 相同點(diǎn):都屬于應(yīng)用層協(xié)議 都是用Request/Response模型進(jìn)行連接的簡歷 都可以在網(wǎng)絡(luò)中傳輸數(shù)據(jù)
9.2 不同點(diǎn):ws使用HTTP來建立連接,但是定義了一系列新的header域,這些域在HTTP中并不會使用 ws連接建立之后,通信雙方都可以在任何時刻向另一方發(fā)送數(shù)據(jù) ws連接建立之后即握手后,TCP套接字保持打開狀態(tài)(套接字是網(wǎng)絡(luò)編程中的一種通信機(jī)制,是支持TCP/IP的網(wǎng)絡(luò)通信的基本操作單元,可以看做是不同主機(jī)之間的進(jìn)程進(jìn)行雙向通信的端點(diǎn),簡單的說就是通信的兩方的一種約定,用套接字中的相關(guān)函數(shù)來完成通信過程),數(shù)據(jù)的傳輸使用幀來傳遞,不再需要Request消息 ws的數(shù)據(jù)幀有序
10. websocket 和 socket區(qū)別??說到這個我不得不用這句話來回答你:就像Java和JavaScript的關(guān)系一樣,兩者沒有絲毫的聯(lián)系。socket即通常說的套接字,它是和網(wǎng)絡(luò)中的運(yùn)輸層打交道的 來源:http://www./content-4-188051.html
|