websocket通訊的建立階段是依賴于http協(xié)議的。最初的握手階段是http協(xié)議,握手完成后就切換到websocket協(xié)議,并完全與http協(xié)議脫離了。
建立通訊時(shí),也是由客戶端主動(dòng)發(fā)起連接請(qǐng)求,服務(wù)端被動(dòng)監(jiān)聽。
通訊一旦建立連接后,通訊就是“全雙工”模式了。也就是說服務(wù)端和客戶端都能在任何時(shí)間自由得發(fā)送數(shù)據(jù),非常適合服務(wù)端要主動(dòng)推送實(shí)時(shí)數(shù)據(jù)的業(yè)務(wù)場景。
交互模式不再是“請(qǐng)求-應(yīng)答”模式,完全由開發(fā)者自行設(shè)計(jì)通訊協(xié)議。
通信的數(shù)據(jù)是基于“幀(frame)”的,可以傳輸文本數(shù)據(jù),也可以直接傳輸二進(jìn)制數(shù)據(jù),效率高。當(dāng)然,開發(fā)者也就要考慮封包、拆包、編號(hào)等技術(shù)細(xì)節(jié)。
沒有同源限制,客戶端可以與任意服務(wù)器通信。
協(xié)議標(biāo)識(shí)符是ws(如果加密,則為wws),服務(wù)器網(wǎng)址是url。
服務(wù)端監(jiān)聽通訊,被動(dòng)提供服務(wù);客戶端主動(dòng)向服務(wù)端發(fā)起連接請(qǐng)求,建立起通訊。
每一次交互都是:客戶端主動(dòng)發(fā)起請(qǐng)求(request),服務(wù)端被動(dòng)應(yīng)答(response)。
服務(wù)端不能主動(dòng)向客戶端推送數(shù)據(jù)。
通信的數(shù)據(jù)是基于文本格式的。二進(jìn)制數(shù)據(jù)(比如圖片等)要利用base64等手段轉(zhuǎn)換為文本后才能傳輸。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>webSocket封裝</title> 8 </head> 9 <body> 10 <script> 11 /* webSocket封裝 12 * @param url: webSocket接口地址與攜帶參數(shù)(必填) 13 * @param onopen(): 連接成功后的回調(diào)函數(shù) 14 * @param onmessage(): 接收到服務(wù)器數(shù)據(jù)后的回調(diào)函數(shù) 15 * @param onclose(): 連接關(guān)閉后的回調(diào)函數(shù) 16 * @param onerror(): 連接發(fā)生錯(cuò)誤后的回調(diào)函數(shù) 17 * @param heartMessage: 發(fā)送給后臺(tái)的心跳包參數(shù)(必填),給服務(wù)器端的心跳包就是定期給服務(wù)器發(fā)送消息 18 * @param timer: 給后臺(tái)傳送心跳包的時(shí)間間隔,不傳時(shí)使用默認(rèn)值3000毫秒 19 * @param isReconnect: 連接斷掉是否重新連接,傳true為重新連接 20 */ 21 function useWebSocket(url,onOpenFunc,onMessageFunc,onCloseFunc,onErrorFunc,heartMessage,timer,isReconnect){ 22 let isConnected = false; //設(shè)置已連接webSocket標(biāo)識(shí) 23 let ws = null; //定義webSocket對(duì)象 24 //創(chuàng)建并連接webSocket 25 let connect = function(){ 26 if(!isConnected){ 27 //若未連接webSocket,則創(chuàng)建一個(gè)新的webSocket 28 console.log(url); 29 ws = new WebSocket(url); 30 isConnected = true; 31 } 32 } 33 //向后臺(tái)發(fā)送心跳消息 34 let heartCheck = function(){ 35 ws.send(JSON.stringify(heartMessage)); 36 } 37 //初始化事件回調(diào)函數(shù) 38 let initEventHandle = function(){ 39 console.log('已連接'); 40 ws.addEventListener('open',function(event){ 41 //給后臺(tái)發(fā)心跳請(qǐng)求 42 heartCheck(); 43 //若傳入函數(shù),執(zhí)行onOpenFunc 44 if(!onOpenFunc){ 45 return false; 46 }else{ 47 onOpenFunc(event); 48 } 49 }) 50 ws.addEventListener('message',function(event){ 51 //接收到任何后臺(tái)的消息都說明當(dāng)前連接是正常的 52 if(!event){ 53 return false; 54 }else{ 55 //若獲取到后臺(tái)消息,則timer毫秒后再次發(fā)起心跳請(qǐng)求給后臺(tái),檢測是否斷開連接 56 setTimeout(()=>{ 57 heartCheck(); //給后臺(tái)發(fā)心跳請(qǐng)求 58 },!timer ? 3000 : timer) 59 } 60 //若傳入了函數(shù),執(zhí)行onMessageFunc 61 if(!onMessageFunc){ 62 return false; 63 }else{ 64 onMessageFunc(event); 65 } 66 }) 67 ws.addEventListener('close',function(event){ 68 //若傳入函數(shù),執(zhí)行onCloseFunc 69 if(!onCloseFunc){ 70 return false; 71 }else{ 72 onCloseFunc(event); 73 } 74 if(isReconnect){ //若斷開立即重新連接標(biāo)志為true 75 connect(); //重新連接webSocket 76 } 77 }) 78 ws.addEventListener('error',function(event){ 79 //若傳入函數(shù),執(zhí)行onErrorFunc 80 if(!onErrorFunc){ 81 return false; 82 }else{ 83 onErrorFunc(event); 84 } 85 if(isReconnect){ //若斷開立即重新連接標(biāo)志為true 86 connect(); //重新連接webSocket 87 } 88 }) 89 } 90 window.onload = function(){ 91 //初始化webSocket 92 (function(){ 93 //1.創(chuàng)建并連接webSocket 94 connect(); 95 //2.初始化事件回調(diào)函數(shù) 96 initEventHandle(); 97 //3.返回是否已連接 98 return ws; 99 })()100 }101 }102 useWebSocket("ws://10.170.6.45:8888/websocket/23", //服務(wù)器url103 null, //onopen的回調(diào)函數(shù) 104 function(event){105 let res = event.data; //后端返回的數(shù)據(jù),onmessage的回調(diào)函數(shù)106 console.log(res);107 },108 null, //onclose的回調(diào)函數(shù) 109 null, //onerror的回調(diào)函數(shù) 110 { //心跳包消息111 "action":"66",112 "eventType":"88",113 "requestId":"123"114 },115 null, //傳送心跳包的間隔時(shí)間116 true //true表示連接斷開立即重新連接 117 )118 </script>119 </body>120 </html>來源:https://www.icode9.com/content-4-592901.html
聯(lián)系客服