h5 socket.io java,从HTML5 WebSocket到Socket.io
HTML5 WebSocket
作為新一代的web標準,HTML5為我們提供了很多有用的東西,比如canvas,本地存儲(已經分離出去了),多媒體編程接口,當然還有我們的WebSocket。WebSocket是HTML5開始提供的一種瀏覽器與服務器間進行全雙工通訊(full-duplex)的網絡技術,可以傳輸基于信息的文本和二進制的數據。它于2011年被IETF定為標準 RFC 6455,同時WebSocket API也被W3C定為標準。
WebSocket產生的背景
黎明前的黑暗——實時web應用的需求
web應用的信息交互過程我想大家或多或少都知道一些,通常是客戶端通過瀏覽器發出一個請求,然后服務器端在接受和審核請求后,進行處理并將結果返回給客戶端,最后由客戶端的瀏覽器將信息呈現出來。這種通信機制在信息交互不是特別頻繁的情況下并沒有太大的問題,但對于那些實時性要求高、海量數據并發的應用來說,就顯得捉襟見肘了,比如現在常見的網頁游戲,證券網站,RSS訂閱推送,網頁實時對話,打車軟件等。通常當客戶端準備呈現一些信息時,這些信息在服務器端很有可能就已經過時了。為了滿足以上那些場景,大佬們研究出來了一些折衷方案,其中最常用的就是普通輪詢和Comet技術,而Comet技術實際上就是輪詢的改進,細分起來Comet有兩種實現方式:
長輪詢機制
流技術機制
長輪詢機制
長輪序是對普通輪詢的改進和提高。普通輪詢簡單來說,就是客戶端每隔一定的時間就先服務器端發送請求,從而以頻繁請求的方式來保持客戶端和服務器端的同步。這種同步方案的最大問題是,客戶端已固定的頻率發送請求時,很可能服務端的數據沒有更新,產生很多無用的網絡傳輸,非常低效。
為了減少無效的網絡傳輸,長輪詢對普通輪詢進行了改進和提高,當服務器端沒有數據更新時,鏈接會保持一段時間周期,知道數據或狀態發生改變或連接時間過期,通過這種機制我們就可以減少很多無效的客戶端和服務器間的交互。當然,如果服務器端的數據變更非常頻繁的話,這種機制并沒有有效的提高性能,和普通輪詢沒有太大的區別,且長輪詢也會耗費更多的資源,比如CPU,內存,帶寬等。
流技術機制
流技術機制簡單來說就是客戶端的頁面使用一個隱藏的窗口向服務端發出一個長連接的請求。服務器接到請求后作出回應,并不斷更新狀態,以保證客戶端和服務器端的連接不過期。通過這種機制就可以將服務器端的信息不斷傳向客戶端,從而保證信息的時效性。但這種機制對于用戶體驗并不友好,需要針對不同的瀏覽器升級不同的方案來改進用戶體驗,同時這種機制如果在并發情況下發生時,會對服務器的資源造成很大壓力。
黎明的到來——WebSocket
正是出于以上幾種解決方案都有著各自的局限性,HTML5 WebSocket也就應運而生了,瀏覽器可以通過JavaScript借助現有的HTTP協議來向服務器發出WebSocket連接的請求,當連接建立后,客戶端和服務器端就可以直接通過TCP連接來直接進行數據交換。這是由于websocket協議本質上就是一個TCP連接,所以在數據傳輸的穩定性和傳輸量上有所保證,且相對于以往的輪詢和Comet技術在性能方面也有了長足的進步:
image
有一點需要注意的是雖然websocket在通信時需要借助HTTP,但它本質上和HTTP有著很大的區別:
WebSocket是一種雙向通信協議,在建立連接之后,WebSocket服務端和客戶端都能主動向對方發送或者接受數據。
WebSocket需要先連接,只有再連接后才能進行相互通信。
他們的關系其實就和這張圖表現的一樣,雖然有相交的部分,但依然有著很大的區別:
image
WebSocket API的用法
由于每個服務器端的語言都有著自己的API,因此首先我們來討論客戶端的API:
// 創建一個socket實例:
var socket = new WebSocket(ws://localhost:9093')
// 打開socket
socket.onopen = (event) => {
// 發送一個初始化消息
socket.send('Hello Server!')
// 服務器有響應數據觸發
socket.onmessage = (event) => {
console.log('Client received a message',event)
}
// 出錯時觸發,并且會關閉連接。這時可以根據錯誤信息進行按需處理
socket.onerror = (event) => {
console.log('error')
}
// 監聽Socket的關閉
socket.onclose = (event) => {
console.log('Client notified socket has closed',event)
}
// 關閉Socket
socket.close(1000, 'closing normally')
}
是不是感覺HTML5 websocket所提供的API賊雞兒簡單,沒錯,就是這么簡單。但有幾點我們需要注意:
在創建socket實例的時候,new WebSocket()接受兩個參數,第一個參數是ws或wss,第二個參數可以選填自定義協議,如果是多協議,可以是數組的方式。
在socket。send(data)發送data時,data可以是各種數據,但只有在建立連接后才能使用。
在使用socket.close(code,[reason])關閉連接時,code和reason都是選填的。
ws和wss
我們在上面提到過,創建一個socket實例時可以選填ws和wss來進行通信協議的確定。他們兩個其實很像HTTP和HTTPS之間的關系。其中ws表示純文本通信,而wss表示使用加密信道通信(TCP+TLS)。那為啥不直接使用HTTP而要自定義通信協議呢?這就要從WebSocket的目的說起來,WebSocket的主要功能就是為了給瀏覽器中的應用與服務器端提供優化的,雙向的通信機制,但這不代表WebScoket只能局限于此,它當然還能夠用于其他的場景,這就需要他可以通過非HTTP協議來進行數據交換,因此WebSocket也就采用了自定義URI模式,以確保就算沒有HTTP,也能進行數據交換。
ws和wss:
ws協議:普通請求,占用與HTTP相同的80端口
wss協議:基于SSL的安全傳輸,占用與TLS相同的443端口。
注:有些HTTP中間設備有時候可能會不理解WebSocket,而導致各種諸如:盲目連接升級,亂修改內容等問題。而WSS就很好的解決了這個問題,它建立了一臺哦端到端的安全通道,這個通道對中間設備模糊了數據,因此中間設備就不能感知到數據,也就無法對請求做一些特殊處理了。
WebSocket協議的規范
以下是一個典型的WebSocket發起請求到響應請求的示例:
客戶端到服務端:
GET / HTTP/1.1
Connection:Upgrade
Host:127.0.0.1:8088
Origin:null
Sec-WebSocket-Extensions:x-webkit-deflate-frame
Sec-WebSocket-Key:puVOuWb7rel6z2AVZBKnfw==
Sec-WebSocket-Version:13
Upgrade:websocket
服務端到客戶端:
HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Server:beetle websocket server
Upgrade:WebSocket
date: Thu, 10 May 2018 07:32:25 GMT
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:content-type
Sec-WebSocket-Accept:FCKgUr8c7OsDsLFeJTWrJw6WO8Q=
我們可以看到,WebSocket協議和HTTP協議乍看并沒有太大的區別,但細看下來,區別還是有些的,這其實是一個握手的http請求,首先請求和響應的,”Upgrade:WebSocket”表示請求的目的就是要將客戶端和服務器端的通訊協議從 HTTP 協議升級到 WebSocket協議。從客戶端到服務器端請求的信息里包含有”Sec-WebSocket-Extensions”、“Sec-WebSocket-Key”這樣的頭信息。這是客戶端瀏覽器需要向服務器端提供的握手信息,服務器端解析這些頭信息,并在握手的過程中依據這些信息生成一個28位的安全密鑰并返回給客戶端,以表明服務器端獲取了客戶端的請求,同意創建 WebSocket 連接。
當握手成功后,這個時候TCP連接就已經建立了,客戶端與服務端就能夠直接通過WebSocket直接進行數據傳遞。不過服務端還需要判斷一次數據請求是什么時候開始的和什么時候是請求的結束的。在WebSocket中,由于瀏覽端和服務端已經打好招呼,如我發送的內容為utf-8 編碼,如果我發送0x00,表示包的開始,如果發送了0xFF,就表示包的結束了。這就解決了黏包的問題。
兼容性情況
瀏覽器 支持情況
Chrome Supported in version 4+
Firefox Supported in version 4+
Internet Explorer Supported in version 10+
Opera Supported in version 10+
Safari Supported in version 5+
Socket.IO
簡單來說Socket.IO就是對WebSocket的封裝,并且實現了WebSocket的服務端代碼。Socket.IO將WebSocket和輪詢(Polling)機制以及其它的實時通信方式封裝成了通用的接口,并且在服務端實現了這些實時機制的相應代碼。也就是說,WebSocket僅僅是Socket.IO實現實時通信的一個子集。Socket.IO簡化了WebSocket API,統一了返回傳輸的API。傳輸種類包括:
WebSocket
Flash Socket
AJAX long-polling
AJAX multipart streaming
IFrame
JSONP polling。
我們來看一下服務端的Socket.IO基本API:
// 引入socke.io
const io = require('socket.io')(80)
// 監聽客戶端連接,回調函數會傳遞本次連接的socket
io.on('connection',function(socket))
// 給所有客戶端廣播消息
io.sockets.emit('String',data)
// 給指定的客戶端發送消息
io.sockets.socket(socketid).emit('String', data)
// 監聽客戶端發送的信息
socket.on('String',function(data))
// 給該socket的客戶端發送消息
socket.emit('String', data)
另外,Socket.IO還提供了一個Node.JS API,它看起來很像客戶端API。所以我們來看看它的實際應用吧:
// socket-server.js
// 需要使用HTTP模塊來啟動服務器和Socket.IO
const http= require('http'),
const io= require('socket.io')
const server= http.createServer(function(req, res){
// 發送HTML的headers和message
res.writeHead(200,{ 'Content-Type': 'text/html' })
res.end('
Hello Socket.IO!
')
});
// 在8080端口啟動服務器
server.listen(8080)
// 創建一個Socket.IO實例,并把它傳遞給服務器
const socket= io.listen(server)
// 添加一個連接監聽器
socket.on('connection', function(client) {
// 連接成功,開始監聽
client.on('message',function(event){
console.log('Received message from client!',event)
})
// 連接失敗
client.on('disconnect',function(){
clearInterval(interval)
console.log('Server has disconnected')
})
})
然后我們就可以啟動這個文件了:
node socket-server.js
然后我們就可以創建一個每秒鐘發送消息到客戶端的發送器了;
var interval= setInterval(function() {
client.send('This is a message from the server,hello world' + new Date().getTime());
},1000);
注:需要注意的是,如果我們想在前端使用socket.IO,我們需要下載這個:
npm install socket.io-client --save
然后再連接網絡:
import io from 'socket.io-client'
const socket = io('ws://localhost:8080')
總結
以上是生活随笔為你收集整理的h5 socket.io java,从HTML5 WebSocket到Socket.io的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos .php 源码,CentO
- 下一篇: php把时间变成整数,php怎么将字符串