溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

WebSocket協(xié)議的作用是什么

發(fā)布時間:2021-06-18 14:50:56 來源:億速云 閱讀:457 作者:Leah 欄目:大數(shù)據(jù)

WebSocket協(xié)議的作用是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

WebSocket 是什么?

WebSocket 是一種網(wǎng)絡(luò)通信協(xié)議。RFC6455 定義了它的通信標(biāo)準(zhǔn)。

WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協(xié)議。

為什么需要 WebSocket ?

了解計算機網(wǎng)絡(luò)協(xié)議的人,應(yīng)該都知道:HTTP 協(xié)議是一種無狀態(tài)的、無連接的、單向的應(yīng)用層協(xié)議。它采用了請求/響應(yīng)模型。通信請求只能由客戶端發(fā)起,服務(wù)端對請求做出應(yīng)答處理。

這種通信模型有一個弊端:HTTP 協(xié)議無法實現(xiàn)服務(wù)器主動向客戶端發(fā)起消息。

這種單向請求的特點,注定了如果服務(wù)器有連續(xù)的狀態(tài)變化,客戶端要獲知就非常麻煩。大多數(shù) Web 應(yīng)用程序?qū)⑼ㄟ^頻繁的異步 JavaScript 和 XML(AJAX)請求實現(xiàn)長輪詢。輪詢的效率低,非常浪費資源(因為必須不停連接,或者 HTTP 連接始終打開)。

因此,工程師們一直在思考,有沒有更好的方法。WebSocket 就是這樣發(fā)明的。WebSocket 連接允許客戶端和服務(wù)器之間進行全雙工通信,以便任一方都可以通過建立的連接將數(shù)據(jù)推送到另一端。WebSocket 只需要建立一次連接,就可以一直保持連接狀態(tài)。這相比于輪詢方式的不停建立連接顯然效率要大大提高。

WebSocket的通信原理和機制

既然是基于瀏覽器的web技術(shù),那么它的通信肯定少不了HTTP,websocket本身雖然也是一種新的應(yīng)用層協(xié)議,但是它也不能夠脫離HTTP而單獨存在。

具體來說,我們在客戶端構(gòu)建一個websocket實例,并且為它綁定一個需要連接到的服務(wù)器地址,當(dāng)客戶端連接到服務(wù)端的時候會向服務(wù)端發(fā)送一個類似下面的HTTP報文:

WebSocket協(xié)議的作用是什么

可以看到,這是一個HTTP的get請求報文,注意該報文中有一個upgrade首部,它的作用是告訴服務(wù)端需要將通信協(xié)議切換到websocket。如果服務(wù)端支持websocket協(xié)議,那么它就會將自己的通信協(xié)議切換到websocket,同時發(fā)給客戶端類似于以下的一個響應(yīng)報文頭:

WebSocket協(xié)議的作用是什么

返回的狀態(tài)碼為101,表示同意客戶端協(xié)議轉(zhuǎn)換請求,并將它轉(zhuǎn)換為websocket協(xié)議。以上過程都是利用HTTP通信完成的,稱之為websocket協(xié)議握手。

經(jīng)過這握手之后,客戶端和服務(wù)端就建立了websocket連接,以后的通信走的都是websocket協(xié)議了。所以總結(jié)為:websocket握手需要借助于HTTP協(xié)議,建立連接后通信過程使用websocket協(xié)議。

同時需要了解的是,該websocket連接還是基于我們剛才發(fā)起HTTP連接的那個TCP連接,一旦建立連接之后,我們就可以進行數(shù)據(jù)傳輸了。在websocket中,提供兩種數(shù)據(jù)傳輸:文本數(shù)據(jù)和二進制數(shù)據(jù)。

基于以上分析,我們可以看到,websocket能夠提供低延遲,高性能的客戶端和服務(wù)端的雙向數(shù)據(jù)通信。它顛覆了之前web開發(fā)的請求處理響應(yīng)模式,并且提供了一種真正意義上的客戶端請求,服務(wù)器推送數(shù)據(jù)的模式,特別適合實時數(shù)據(jù)交互應(yīng)用開發(fā)

WebSocket 客戶端

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>菜鳥教程(runoob.com)</title>
    
      <script type="text/javascript">
      WebSocketTest();
         function WebSocketTest()
         {
            if ("WebSocket">

客戶端 API

以下 API 用于創(chuàng)建 WebSocket 對象。

var Socket = new WebSocket(url, [protocol] );

以上代碼中的第一個參數(shù) url, 指定連接的 URL。第二個參數(shù) protocol 是可選的,指定了可接受的子協(xié)議。

WebSocket 屬性

以下是 WebSocket 對象的屬性。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:

屬性描述
Socket.readyState只讀屬性 readyState 表示連接狀態(tài),可以是以下值:0 - 表示連接尚未建立。1 - 表示連接已建立,可以進行通信。2 - 表示連接正在進行關(guān)閉。3 - 表示連接已經(jīng)關(guān)閉或者連接不能打開。
Socket.bufferedAmount只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,但是還沒有發(fā)出的 UTF-8 文本字節(jié)數(shù)。
WebSocket 事件

以下是 WebSocket 對象的相關(guān)事件。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:

事件事件處理程序描述
openSocket.onopen連接建立時觸發(fā)
messageSocket.onmessage客戶端接收服務(wù)端數(shù)據(jù)時觸發(fā)
errorSocket.onerror通信發(fā)生錯誤時觸發(fā)
closeSocket.onclose連接關(guān)閉時觸發(fā)
WebSocket 方法

以下是 WebSocket 對象的相關(guān)方法。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:

方法描述
Socket.send()使用連接發(fā)送數(shù)據(jù)
Socket.close()關(guān)閉連接

WebSocket 服務(wù)端

package com.gaofei.servlet;

import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;

import com.gaofei.entry.MyMessageInbound;

public class DemoServlet extends WebSocketServlet{

	private static final long serialVersionUID = -4853540828121130946L;
    /*
     * (non-Javadoc)
     * 創(chuàng)建一個webSocekt對象,第一個參數(shù)表示協(xié)議,第二個參數(shù)httqrequest對象
     * @see org.apache.catalina.websocket.WebSocketServlet#createWebSocketInbound(java.lang.String, javax.servlet.http.HttpServletRequest)
     *  返回一個綁定的消息
     */
    
    @Override
    protected StreamInbound createWebSocketInbound(String str,HttpServletRequest req) {
    	System.out.println( req.getRemoteAddr());
    	System.out.println(str);
        return new MyMessageInbound();
    }
  


}
package com.gaofei.entry;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;

public class MyMessageInbound  extends MessageInbound{
	 WsOutbound wsOutbount;//用于向客戶端發(fā)送數(shù)據(jù)對象
	@Override
	protected void onBinaryMessage(ByteBuffer arg0) throws IOException {//接收數(shù)據(jù)觸發(fā),二進制消息文件
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void onTextMessage(CharBuffer message) throws IOException {//接收數(shù)據(jù)觸發(fā),文本消息文件
           System.out.println("收到文本消息:"+message);
           int i=1;
           Long ms0=System.currentTimeMillis()/10000;
           for(;i>0;i++) {
        	   Long ms01=System.currentTimeMillis()/1000;
        	   Long ms01_0=ms01-ms0;
        	   if(ms01_0>10) {
        		   wsOutbount.writeTextMessage(CharBuffer.wrap(i+"來了")); //客戶端發(fā)送的數(shù)據(jù)
        		   ms0=System.currentTimeMillis()/1000;
        	   }
           }
	}
    @Override
    protected void onClose(int status) {//斷開連接觸發(fā)
    	// TODO Auto-generated method stub
    	super.onClose(status);
    	System.out.println("斷開握手");
    }
    @Override
    protected void onOpen(WsOutbound outbound) {//連接成功觸發(fā)
    	
    	super.onOpen(outbound);
    	System.out.println("握手成功");
    	this.wsOutbount=outbound;
    	try {
			this.wsOutbount.writeTextMessage(CharBuffer.wrap("你好??!"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
}

pom 配置文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>om.gaof.webSocketServer</groupId>
  <artifactId>webSocketServer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
	  <dependencies>
	<dependency>
		<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-catalina</artifactId>
			<version>7.0.39</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-coyote</artifactId>
			<version>7.0.39</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	
	<build>
	    <finalName>websocketServer</finalName>
	      <plugins>           
        <!-- java編譯插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <!-- 指定端口 -->
                <port>8080</port>
                <!-- 請求路徑 -->
                <path>/</path>
            </configuration>                
        </plugin>
    </plugins>
	</build>
</project>

web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>wsServlet</servlet-name>
<servlet-class>com.gaofei.servlet.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>wsServlet</servlet-name>
<url-pattern>/wsServlet</url-pattern>
</servlet-mapping>
</web-app>

WebSocket 代理

如果把 WebSocket 的通信看成是電話連接,Nginx 的角色則像是電話接線員,負責(zé)將發(fā)起電話連接的電話轉(zhuǎn)接到指定的客服。

Nginx 從 1.3 版開始正式支持 WebSocket 代理。如果你的 web 應(yīng)用使用了代理服務(wù)器 Nginx,那么你還需要為 Nginx 做一些配置,使得它開啟 WebSocket 代理功能。

以下為參考配置:

server {
  # this section is specific to the WebSockets proxying
  location /socket.io {
    proxy_pass http://app_server_wsgiapp/socket.io;
    proxy_redirect off;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 600;
  }
}

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI