<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # WebSocket協議 &nbsp;&nbsp;&nbsp;&nbsp;WebSocket協議是一種網絡通信協議,是HTML5之后提出的一種在單個TCP上進行`全雙工`通訊的協議。可以使服務端主動的向客戶端發送消息,常用于`推送服務。`其特點如下: * HTTP協議(1.0)是單向的沒有連接狀態的協議,客戶端瀏覽器為了獲取服務器的動態變化信息,需要配合JavaScript和AJAX進行不斷的異步`輪詢請求`,需要不斷的建立連接,非常耗費資源。 * WebSocket能夠使任一方主動的建立起連接,并且連接只要建立一次就`一直保持連接`狀態。 &nbsp;&nbsp;&nbsp;&nbsp;WebSocket并不是全新的協議,而是利用HTTP協議來建立連接的,其創建過程如下: 1. 瀏覽器發送HTTP請求 ~~~ ?GET ws://localhost:3000/hello HTTP/1.1 ?Host: localhost ?Upgrade: websocket ?Connection: Upgrade ?Origin: http://localhost:3000 ?Sec-WebSocket-Key: client-random-string ?Sec-WebSocket-Version: 13 ~~~ 說明: * GET請求的地址不是類似`/path/`,而是以`ws://`開頭的地址; * 請求頭`Upgrade: websocket`和`Connection: Upgrade`表示這個連接將要被轉換為WebSocket連接; * `Sec-WebSocket-Key`是用于標識這個連接,并非用于加密數據; * `Sec-WebSocket-Version`指定了WebSocket的協議版本。 2. 服務器接受該請求,就會返回下面的響應: ~~~ ?HTTP/1.1 101 Switching Protocols ?Upgrade: websocket ?Connection: Upgrade ?Sec-WebSocket-Accept: server-random-string ~~~ &nbsp;&nbsp;&nbsp;&nbsp;該響應代碼`101`表示本次連接的HTTP協議即將被更改,更改后的協議就是`Upgrade: websocket`指定的WebSocket協議。 3. WebSocket連接建立,服務器端可以主動的發送消息給瀏覽器,可以是二進制數據和文本數據。 &nbsp;&nbsp;&nbsp;&nbsp; 下面是如何在前端分離的項目中使用WebSocket協議,前端Vue,后端Spring Boot。 ## WebSocket客戶端 適用于支持html5的瀏覽器,其開放的API(不需要引入)為: 1. 創建Web Socket連接 ~~~ ?var Socket = new WebSocket(url, [protocol] ); ~~~ url表示指定連接的URL,protocol是子協議,可選。 對象屬性: ~~~ ?Socket.readyState: 連接狀態,0表示連接未建立;1表示連接建立,可以進行通信;2表示連接正在關閉;3表示連接已經關閉,并且不能打開。 ?Socket.bufferAmount:等待傳輸的隊列。 ~~~ 對象事件: | 事件 | 事件處理程序 | 描述 | | --- | --- | --- | | open | Socket.onopen | 連接建立時觸發 | | message | Socket.onmessage | 瀏覽器客戶端接收服務器的信息時觸發 | | error | Socket.onerror | 通信發生錯誤時觸發 | | close | Socket.onclose | 連接關閉時觸發 | 對象方法: * Socket.send():使用連接發送數據。 * Socket.close():關閉連接。 ~~~ ?// 初始化一個 WebSocket 對象 ?var socket = new WebSocket('ws://localhost:9998/echo'); ?? ?// 建立 web socket 連接成功觸發事件 ?socket.onopen = function() { ? ?// 使用 send() 方法發送數據 ? ?socket.send('發送數據'); ? ?alert('數據發送中...'); ?}; ?? ?// 接收服務端數據時觸發事件 ?socket.onmessage = function(evt) { ? ?var received_msg = evt.data; ? ?alert('數據已接收...'); ?}; ?? ?// 斷開 web socket 連接成功觸發事件 ?socket.onclose = function() { ? ?alert('連接已關閉...'); ?}; ~~~ &nbsp;&nbsp;&nbsp;&nbsp; ### Vue使用web socket ~~~ ?// 建立web socket連接 ?webSocket() { ? ? ?if ('WebSocket' in window) { ? ? ?this.websocket = new WebSocket("ws://localhost:8081/websocket/hello"); ? ? } else { ? ? ?console.log("你的瀏覽器還不支持web socket"); ?} ?console.log(this.websocket); ?this.websocket.onopen = this.webSocketOnOpen; ?this.websocket.onclose = this.webSocketOnClose; ?this.websocket.onmessage = this.webSocketOnMessage; ?this.websocket.onerror = this.webSocketOnError; ?}, ?? ?// 連接建立之后 ?webSocketOnOpen() { ? ? ?console.log("與后端建立連接"); ? ? ?var data = "這里是端口8001建立連接"; ? ? ?this.websocket.send(data); ?}, ?? ?// 連接關閉之后 ?webSocketOnClose() { ? ? ?console.log("與后端關閉連接"); ?}, ?? ?// 發送消息 ?webSocketOnMessage(res) { ? ? ?console.log("接收到后端發送回來的消息"); ? ? ?console.log(res.data) ?}, ?? ?// 發生錯誤 ?webSocketOnError() { ? ? ?console.log("發生錯誤~"); ?}, ~~~ 使用原生的web socket就行了,也有封裝了web socket的工具可以使用。 &nbsp;&nbsp;&nbsp;&nbsp; ## WebSocket服務端 如果是使用Tomcat服務器的話,要版本7以上才支持,使用Spring Boot整合WebSocket的過程如下: 1. 引入依賴 ~~~ ?<dependency> ? ? ?<groupId>org.springframework.boot</groupId> ? ? ?<artifactId>spring-boot-starter-websocket</artifactId> ?</dependency> ~~~ 2. 創建核心配置類 ~~~ ?import org.springframework.context.annotation.Bean; ?import org.springframework.context.annotation.Configuration; ?import org.springframework.messaging.simp.config.MessageBrokerRegistry; ?import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; ?import org.springframework.web.socket.config.annotation.StompEndpointRegistry; ?import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; ?import org.springframework.web.socket.server.standard.ServerEndpointExporter; ?? ?/** ? * spring boot web socket 核心配置類 ? */ ?@Configuration ?public class WebSocketConfig { ? /** ? ? ? * 配置服務端點導出器 ? ? ? * @return ? ? ? */ ? ? ?@Bean ? ? ?public ServerEndpointExporter serverEndpointExporter() { ? ? ? ? ?return new ServerEndpointExporter(); ? ? } ?? ?} ~~~ 3. 創建服務端點 ~~~ ?import lombok.extern.slf4j.Slf4j; ?import org.springframework.stereotype.Component; ?import org.springframework.web.bind.annotation.RequestParam; ?? ?import javax.websocket.*; ?import javax.websocket.server.PathParam; ?import javax.websocket.server.ServerEndpoint; ?import java.io.IOException; ?import java.util.Map; ?import java.util.concurrent.CopyOnWriteArraySet; ?? ?/** ? * 后端實現web socket ? */ ?@Component ?@ServerEndpoint("/hello") ?@Slf4j ?public class WebSocketServer { ? ? ?/** ? ? ? * 靜態變量,用來記錄當前在線連接數 ? ? ? * 注意線程安全問題 ? ? ? */ ? ? ?private static int onlineCount = 0; ? ? ? ? ? ?/** ? ? ? * concurrent包的線程安全集合,存放每個客戶端對應的web socket對象 ? ? ? */ ? ? ?private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); ?? ? ? ?/** ? ? ? * 與某個客戶端的連接會話,需要聽過它來給客戶端發送數據 ? ? ? * 每個前端的WebSocket對象建立起來的有一個session對象 ? ? ? */ ? ? ?private Session session; ?? ? ? ?/** ? ? ? * 連接建立成功調用的方法 ? ? ? */ ? ? ?@OnOpen ? ? ?public void onOpen(Session session) { ? ? ? ? ?this.session = session; ? ? ? ? ?System.out.println("session = " + session); ? ? ? ? ?// 添加當前web socket對象 ? ? ? ? ?webSocketSet.add(this); ? ? ? ? ?// 累加在線人數 ? ? ? ? ?addOnlineCount(); ? ? ? ? ?log.info("有新連接加入!當前在線人數為" + getOnlineCount()); ? ? ? ? ?try { ? ? ? ? ? ? ?sendMessage("有新連接加入!當前在線人數為" + getOnlineCount()); ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ?log.error("websocket IO異常"); ? ? ? ? } ? ? } ?? ? ? ?/** ? ? ? * 連接關閉調用的方法 ? ? ? */ ? ? ?@OnClose ? ? ?public void onClose() { ? ? ? ? ?// 將連接的web socket對象從set中移除 ? ? ? ? ?webSocketSet.remove(this); ? ? ? ? ?// 在線人數-1 ? ? ? ? ?subOnlineCount(); ? ? ? ? ?log.info("有一連接關閉!當前在線人數為" + getOnlineCount()); ? ? } ?? ? ? ?/** ? ? ? * 收到客戶端消息后調用的方法 ? ? ? * @param message 客戶端發送過來的消息 ? ? ? */ ? ? ?@OnMessage ? ? ?public void onMessage(String message, Session session) { ? ? ? ? ?log.info("來自客戶端的消息:" + message); ?? ? ? ? ? ?//群發消息 ? ? ? ? ?for (WebSocketServer item : webSocketSet) { ? ? ? ? ? ? ?try { ? ? ? ? ? ? ? ? ?item.sendMessage(message); ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? ?e.printStackTrace(); ? ? ? ? ? ? } ? ? ? ? } ? ? } ?? ? ? ?/** ? ? ? * 發生錯誤 ? ? ? * @param session ? ? ? * @param error ? ? ? */ ? ? ?@OnError ? ? ?public void onError(Session session, Throwable error) { ? ? ? ? ?log.error("發生錯誤"); ? ? ? ? ?error.printStackTrace(); ? ? } ?? ? ? ?/** ? ? ? * 給客戶端瀏覽器發送消息 ? ? ? * @param message ? ? ? * @throws IOException ? ? ? */ ? ? ?public void sendMessage(String message) throws IOException { ? ? ? ? ?this.session.getBasicRemote().sendText(message); ? ? } ? ? ?/** ? ? ? * 群發自定義消息 ? ? ? * */ ? ? ?public static void sendInfo(String message) throws IOException { ? ? ? ? ?log.info(message); ? ? ? ? ?for (WebSocketServer item : webSocketSet) { ? ? ? ? ? ? ?try { ? ? ? ? ? ? ? ? ?item.sendMessage(message); ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? ?continue; ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ?public static synchronized int getOnlineCount() { ? ? ? ? ?return onlineCount; ? ? } ? ? ?public static synchronized void addOnlineCount() { ? ? ? ? ?WebSocketServer.onlineCount++; ? ? } ? ? ?public static synchronized void subOnlineCount() { ? ? ? ? ?WebSocketServer.onlineCount--; ? ? } ?} ~~~ 如果要獲取前端發送的消息可用: ~~~ ?@Component ?@ServerEndPoint("/hello/{name}/{age}") ?public class WebSocketServer { ? ? ?@OnOpen ? ? ?public void onOpen(@PathParam("name")String name, @PathParam("age")int age) { ? ? ? ? ? ? ? } ?} ~~~ &nbsp;&nbsp;&nbsp;&nbsp; 【參考】廖雪峰的官方網站[https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096](https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096) &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看