加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • Part 01●??WebSocket是什么??●
    • Part 02●??Websocket報(bào)文?●
    • Part 03●??代碼實(shí)現(xiàn)?●
    • Part 04●??結(jié)束語(yǔ)?●
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

五分鐘技術(shù)趣談 | 淺談WebSocket協(xié)議在Web領(lǐng)域的應(yīng)用

2023/12/08
3388
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

作者:浦春城,單位:中國(guó)移動(dòng)智慧家庭運(yùn)營(yíng)中心

WebSocket是一種雙向通信協(xié)議,主要應(yīng)用在Web瀏覽器,解決服務(wù)器端主動(dòng)向?yàn)g覽器推送消息的問(wèn)題。WebSocket常見(jiàn)的應(yīng)用場(chǎng)景有頁(yè)游、視頻網(wǎng)站、在線文檔、股票網(wǎng)站等。

Part 01●??WebSocket是什么??

WebSocket是一種在Web應(yīng)用程序中提供雙向通信的協(xié)議。它允許服務(wù)器主動(dòng)向客戶端推送數(shù)據(jù),而不是像傳統(tǒng)的HTTP請(qǐng)求-響應(yīng)模式一樣,客戶端必須發(fā)送請(qǐng)求才能獲取數(shù)據(jù)。WebSocket 最早是在HTML5中引入的,建立在HTTP協(xié)議之上,使用握手階段來(lái)升級(jí)連接,然后通過(guò)保持連接的狀態(tài)來(lái)實(shí)現(xiàn)實(shí)時(shí)通信。

與傳統(tǒng)的HTTP協(xié)議相比,WebSocket具有以下優(yōu)勢(shì):

⑴ 增強(qiáng)實(shí)時(shí)性

服務(wù)器可以隨時(shí)主動(dòng)給客戶端下發(fā)數(shù)據(jù),相對(duì)于HTTP請(qǐng)求需要等待客戶端發(fā)起請(qǐng)求服務(wù)端才能響應(yīng),延遲明顯更少。和傳統(tǒng)的輪詢比較,WebSocket也可以在短時(shí)間內(nèi)更有效率地傳遞數(shù)據(jù);

⑵ 維持連接狀態(tài)

在一些需要身份認(rèn)證的場(chǎng)景下,HTTP請(qǐng)求可能需要在每個(gè)請(qǐng)求都攜帶狀態(tài)信息(服務(wù)器不記錄每次的請(qǐng)求和響應(yīng)信息),而WebSocket一次連接建立后就會(huì)保持住會(huì)話狀態(tài),這就使其成為一種有狀態(tài)的協(xié)議,后續(xù)通信時(shí)就可以省略部分狀態(tài)信息;

⑶ 更靈活的擴(kuò)展支持

開發(fā)者可以對(duì)WebSocket自定義二進(jìn)制幀,相對(duì)HTTP,可以更輕松地處理二進(jìn)制內(nèi)容,此外開發(fā)者也自行擴(kuò)展協(xié)議、實(shí)現(xiàn)部分自定義的子協(xié)議;

⑷ 更好的壓縮效果

WebSocket在適當(dāng)?shù)臄U(kuò)展支持下,可以沿用之前內(nèi)容的上下文,在傳遞類似的數(shù)據(jù)時(shí),可以顯著地提高壓縮率。

Part 02●??Websocket報(bào)文?

2.1 報(bào)文格式

- 第0個(gè)字節(jié)

0位(FIN):0表示報(bào)文沒(méi)有結(jié)束,1表示報(bào)文結(jié)束。

1-3位(RSV1、RSV2、RSV3):保留字段,一般全部為0。也可用于擴(kuò)展自己的協(xié)議。

4-7位(opcode):報(bào)文類型。0 代表一個(gè)繼續(xù)幀,1代表文本幀,2代表二進(jìn)制幀,8 代表連接關(guān)閉,9 代表ping,10代表pong。

- 第1個(gè)字節(jié)

8位(MASK):1表示需要掩碼操作,0表示不需要。如果為1,數(shù)據(jù)幀的masking-key屬性會(huì)存在一個(gè)值,接收方會(huì)利用這個(gè)值來(lái)進(jìn)行解掩碼操作,所有從客戶端傳輸?shù)椒?wù)器的數(shù)據(jù)幀的Mask都被設(shè)置為1。

9-15位(Payload len):表示Payload data的長(zhǎng)度。如果值是0~125,則真實(shí)長(zhǎng)度就是前7位表示;如果值是126,則真實(shí)長(zhǎng)度就是后16位(Extended payload length 126);如果值是127,則真實(shí)長(zhǎng)度就是后64位(Extended payload length 127)

2.2 報(bào)文樣例

- ping幀,Opcode=9,Mask=1,Payload len=0,Masking-Key有內(nèi)容

- pong幀,Opcode=10,Mask=0,Payload len=0,Masking-Key為空

- 文本幀,Opcode=1,Mask=0,Payload len=84,Masking-Key為空

Part 03●??代碼實(shí)現(xiàn)?

接下來(lái),一起動(dòng)手編寫WebSocket服務(wù)端和客戶端,這里提供一個(gè)java版的服務(wù)端demo和一個(gè)html版的客戶端demo。

1、服務(wù)端demo是一個(gè)springboot項(xiàng)目

- 引用spring-boot-starter-websocket依賴

<!-- WebSocket --><dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-websocket</artifactId></dependency>

- session管理

public class WsSessionManager {

    public static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();

    public static void add(String key, WebSocketSession session) {        SESSION_POOL.put(key, session);    }

    public static WebSocketSession remove(String key) {        return SESSION_POOL.remove(key);    }

    public static void removeAndClose(String key) {        WebSocketSession session = remove(key);        if (session != null) {            try {                session.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }

    public static WebSocketSession get(String key) {        return SESSION_POOL.get(key);    }}

- 消息處理

@Component@Slf4jpublic class MyWsHandler extends AbstractWebSocketHandler {

    @Override    public void afterConnectionEstablished(WebSocketSession session) throws Exception {        log.info("建立ws連接,sessionId:{}", session.getId());        WsSessionManager.add(session.getId(), session);    }

    @Override    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {        // 獲得客戶端傳來(lái)的消息        String payload = message.getPayload();        log.info("server 接收到消息, sessionId " + session.getId() + ", payload: " + payload);        session.sendMessage(new TextMessage("server 發(fā)送給的消息 " + payload + ",發(fā)送時(shí)間:" + LocalDateTime.now().toString()));    }

    @Override    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {        log.info("發(fā)送二進(jìn)制消息, sessionId " + session.getId());    }

    @Override    public void handleTransportError(WebSocketSession session, Throwable exception) {        log.error("異常處理, sessionId " + session.getId());

- WebSocket配置

@Configuration@EnableWebSocketpublic class WsServerConfig implements WebSocketConfigurer {

    @Autowired    private MyWsHandler myWsHandler;

    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        registry.addHandler(myWsHandler, "myWs")                //允許跨域                .setAllowedOrigins("*");    }

}

2、客戶端demo是一個(gè)html網(wǎng)頁(yè)

<!doctype html><form name="publish">  <input type="text" name="message" maxlength="50"/>  <input type="submit" value="Send"/></form>

<div id="messages"></div>

<script>let url='ws://127.0.0.1:8889/myWs';let socket = new WebSocket(url);

// send message from the formdocument.forms.publish.onsubmit = function() {  let outgoingMessage = this.message.value;  socket.send(outgoingMessage);  return false;};

// handle incoming messagessocket.onmessage = function(event) {  let incomingMessage = event.data;  showMessage(incomingMessage);};

socket.onclose = event => console.log(`Closed ${event.code}`);

// show message in div#messagesfunction showMessage(message) {  let messageElem = document.createElement('div');  messageElem.textContent = message;  document.getElementById('messages').prepend(messageElem);

Part 04●??結(jié)束語(yǔ)?

WebSocket適用于服務(wù)器端需要快速向?yàn)g覽器發(fā)送消息的場(chǎng)景,例如網(wǎng)頁(yè)游戲、視頻網(wǎng)站、在線文檔、運(yùn)維工具等。瀏覽器可以看做是一個(gè)瘦客戶端,它不提供直接操作tcp長(zhǎng)連接的編程接口,也無(wú)法簡(jiǎn)單地集成消息組件客戶端。在使用瀏覽器作為客戶端的場(chǎng)景下,WebSocket是最常用的服務(wù)器端主動(dòng)推送方案。

當(dāng)然,有很多種技術(shù)可以實(shí)現(xiàn)服務(wù)器端向客戶端主動(dòng)推送消息,WebSocket只是其中一種,其他常見(jiàn)的方案還有tcp長(zhǎng)連接、消息組件(如mqtt、kafka)等,不過(guò)各有優(yōu)缺點(diǎn),這個(gè)可以在日后進(jìn)一步學(xué)習(xí)。

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
KSZ8463MLI 1 Microchip Technology Inc DATACOM, MANCHESTER ENCODER
$6.84 查看
LAN8710AI-EZK 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER, QCC32, 5 X 5 MM, 0.90 MM HEIGHT, ROHS COMPLIANT, QFN-32

ECAD模型

下載ECAD模型
$1.56 查看
BT121-A-V2 1 Silicon Laboratories Inc Telecom Circuit, 1-Func, MODULE-33

ECAD模型

下載ECAD模型
$27.77 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

移動(dòng)Labs是中國(guó)移動(dòng)的社交化新媒體平臺(tái),是面向外部行業(yè)及產(chǎn)業(yè)鏈合作伙伴的信息發(fā)布、業(yè)務(wù)發(fā)展和產(chǎn)業(yè)推進(jìn)門戶。