最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于java實(shí)現(xiàn)websocket協(xié)議過(guò)程詳解

 更新時(shí)間:2020年09月22日 09:29:33   作者:手撕高達(dá)的村長(zhǎng)  
這篇文章主要介紹了基于java實(shí)現(xiàn)websocket協(xié)議過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

最近了解了下websocket和socket這個(gè)東西,說(shuō)不得不來(lái)說(shuō)下為何要使用 WebSocket ,和為何不用http。

為何需要WebSocket ?

HTTP 協(xié)議是一種無(wú)狀態(tài)的、無(wú)連接的、單向的應(yīng)用層協(xié)議。它采用了請(qǐng)求/響應(yīng)模型。通信請(qǐng)求只能由客戶端發(fā)起,服務(wù)端對(duì)請(qǐng)求做出應(yīng)答處理。

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

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

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

下面來(lái)一個(gè)例子,實(shí)現(xiàn)web客戶端和服務(wù)器端的連續(xù)通訊。

客戶端頁(yè)面index.html

<!DOCTYPE html>
<html>
<head>
  <title>Java后端WebSocket的Tomcat實(shí)現(xiàn)</title>
</head>
<body>
  Welcome<br/><input id="text" type="text"/>
  <button onclick="send()">發(fā)送消息</button>
  <hr/>
  <button onclick="closeWebSocket()">關(guān)閉WebSocket連接</button>
  <hr/>
  <div id="message"></div>
</body>
 
<script type="text/javascript">
  var websocket = null;
  //判斷當(dāng)前瀏覽器是否支持WebSocket
  if ('WebSocket' in window) {
    websocket = new WebSocket("ws://localhost:8080/Testwebsocket/websocket");
  }
  else {
    alert('當(dāng)前瀏覽器 Not support websocket')
  }
 
  //連接發(fā)生錯(cuò)誤的回調(diào)方法
  websocket.onerror = function () {
    setMessageInnerHTML("WebSocket連接發(fā)生錯(cuò)誤");
  };
 
  //連接成功建立的回調(diào)方法
  websocket.onopen = function () {
    setMessageInnerHTML("WebSocket連接成功");
  }
 
  //接收到消息的回調(diào)方法
  websocket.onmessage = function (event) {
    setMessageInnerHTML(event.data);
  }
 
  //連接關(guān)閉的回調(diào)方法
  websocket.onclose = function () {
    setMessageInnerHTML("WebSocket連接關(guān)閉");
  }
 
  //監(jiān)聽(tīng)窗口關(guān)閉事件,當(dāng)窗口關(guān)閉時(shí),主動(dòng)去關(guān)閉websocket連接,防止連接還沒(méi)斷開(kāi)就關(guān)閉窗口,server端會(huì)拋異常。
  window.onbeforeunload = function () {
    closeWebSocket();
  }
 
  //將消息顯示在網(wǎng)頁(yè)上
  function setMessageInnerHTML(innerHTML) {
    document.getElementById('message').innerHTML += innerHTML + '<br/>';
  }
 
  //關(guān)閉WebSocket連接
  function closeWebSocket() {
    websocket.close();
  }
 
  //發(fā)送消息
  function send() {
    var message = document.getElementById('text').value;
    websocket.send(message);
  }
</script>
</html>

服務(wù)器端:服務(wù)器端的很簡(jiǎn)單。

1.創(chuàng)建一個(gè)web 的maven項(xiàng)目

2.引入一個(gè)包

<!-- websocket -->
  <dependency>
   <groupId>javax</groupId>
   <artifactId>javaee-api</artifactId>
   <version>7.0</version>
   <scope>provided</scope>
  </dependency>

3.創(chuàng)建一個(gè)類(lèi)。

package com.sun.web.handler;
 
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
 
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
 
/**
 * @ServerEndpoint 注解是一個(gè)類(lèi)層次的注解,它的功能主要是將目前的類(lèi)定義成一個(gè)websocket服務(wù)器端,
 * 注解的值將被用于監(jiān)聽(tīng)用戶連接的終端訪問(wèn)URL地址,客戶端可以通過(guò)這個(gè)URL來(lái)連接到WebSocket服務(wù)器端
 */
@ServerEndpoint("/websocket")
public class WebSocketTest {
  //靜態(tài)變量,用來(lái)記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計(jì)成線程安全的。
  private static int onlineCount = 0;
 
  //concurrent包的線程安全Set,用來(lái)存放每個(gè)客戶端對(duì)應(yīng)的MyWebSocket對(duì)象。若要實(shí)現(xiàn)服務(wù)端與單一客戶端通信的話,可以使用Map來(lái)存放,其中Key可以為用戶標(biāo)識(shí)
  private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();
 
  //與某個(gè)客戶端的連接會(huì)話,需要通過(guò)它來(lái)給客戶端發(fā)送數(shù)據(jù)
  private Session session;
 
  /**
   * 連接建立成功調(diào)用的方法
   * @param session 可選的參數(shù)。session為與某個(gè)客戶端的連接會(huì)話,需要通過(guò)它來(lái)給客戶端發(fā)送數(shù)據(jù)
   */
  @OnOpen
  public void onOpen(Session session){
    this.session = session;
    webSocketSet.add(this);   //加入set中
    addOnlineCount();      //在線數(shù)加1
    System.out.println("有新連接加入!當(dāng)前在線人數(shù)為" + getOnlineCount());
  }
 
  /**
   * 連接關(guān)閉調(diào)用的方法
   */
  @OnClose
  public void onClose(){
    webSocketSet.remove(this); //從set中刪除
    subOnlineCount();      //在線數(shù)減1
    System.out.println("有一連接關(guān)閉!當(dāng)前在線人數(shù)為" + getOnlineCount());
  }
 
  /**
   * 收到客戶端消息后調(diào)用的方法
   * @param message 客戶端發(fā)送過(guò)來(lái)的消息
   * @param session 可選的參數(shù)
   */
  @OnMessage
  public void onMessage(String message, Session session) {
    System.out.println("來(lái)自客戶端的消息:" + message);
    //群發(fā)消息
    for(WebSocketTest item: webSocketSet){
      try {
        item.sendMessage(message);
      } catch (IOException e) {
        e.printStackTrace();
        continue;
      }
    }
  }
 
  /**
   * 發(fā)生錯(cuò)誤時(shí)調(diào)用
   * @param session
   * @param error
   */
  @OnError
  public void onError(Session session, Throwable error){
    System.out.println("發(fā)生錯(cuò)誤");
    error.printStackTrace();
  }
 
  /**
   * 這個(gè)方法與上面幾個(gè)方法不一樣。沒(méi)有用注解,是根據(jù)自己需要添加的方法。
   * @param message
   * @throws IOException
   */
  public void sendMessage(String message) throws IOException{
    this.session.getBasicRemote().sendText(message);
    //this.session.getAsyncRemote().sendText(message);
  }
 
  public static synchronized int getOnlineCount() {
    return onlineCount;
  }
 
  public static synchronized void addOnlineCount() {
    WebSocketTest.onlineCount++;
  }
 
  public static synchronized void subOnlineCount() {
    WebSocketTest.onlineCount--;
  }
}

4.以上三步就OK了,然后就是用tomcat運(yùn)行就行了。

效果如圖:

后期整合了springboot + websocket,并且實(shí)現(xiàn)了定時(shí)推送給前,還可以實(shí)現(xiàn)推送給某個(gè)人,不過(guò)需要參數(shù).

地址 :

https://github.com/sun2955/spring-test-study.git

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java方法重載Overload原理及使用解析

    Java方法重載Overload原理及使用解析

    這篇文章主要介紹了Java方法重載Overload原理及使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 使用Mybatis時(shí)SqlSessionFactory對(duì)象總是報(bào)空指針

    使用Mybatis時(shí)SqlSessionFactory對(duì)象總是報(bào)空指針

    本文主要介紹了使用Mybatis時(shí)SqlSessionFactory對(duì)象總是報(bào)空指針,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • Java斗地主發(fā)牌課程設(shè)計(jì)

    Java斗地主發(fā)牌課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了Java斗地主發(fā)牌課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • SpringBoot訪問(wèn)不到controller的解決方案

    SpringBoot訪問(wèn)不到controller的解決方案

    這篇文章主要介紹了SpringBoot訪問(wèn)不到controller的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • MyBatis-Plus邏輯刪除和字段自動(dòng)填充的實(shí)現(xiàn)

    MyBatis-Plus邏輯刪除和字段自動(dòng)填充的實(shí)現(xiàn)

    本文主要介紹了MyBatis-Plus邏輯刪除和字段自動(dòng)填充的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • @FeignClient?實(shí)現(xiàn)簡(jiǎn)便http請(qǐng)求封裝方式

    @FeignClient?實(shí)現(xiàn)簡(jiǎn)便http請(qǐng)求封裝方式

    這篇文章主要介紹了@FeignClient?實(shí)現(xiàn)簡(jiǎn)便http請(qǐng)求封裝方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 詳解ElasticSearch6.4.0集群搭建

    詳解ElasticSearch6.4.0集群搭建

    這篇文章主要介紹了詳解ElasticSearch6.4.0集群搭建,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • java8 實(shí)現(xiàn)提取集合對(duì)象的每個(gè)屬性

    java8 實(shí)現(xiàn)提取集合對(duì)象的每個(gè)屬性

    這篇文章主要介紹了java8 實(shí)現(xiàn)提取集合對(duì)象的每個(gè)屬性方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • 基于SSM框架之個(gè)人相冊(cè)示例代碼

    基于SSM框架之個(gè)人相冊(cè)示例代碼

    本篇文章主要介紹了基于SSM框架之個(gè)人相冊(cè)示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • SpringBoot指標(biāo)監(jiān)控功能實(shí)現(xiàn)

    SpringBoot指標(biāo)監(jiān)控功能實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot指標(biāo)監(jiān)控功能實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06

最新評(píng)論

马鞍山市| 漳平市| 平塘县| 赞皇县| 双流县| 苏州市| 远安县| 东源县| 辛集市| 阿城市| 迁安市| 华宁县| 武冈市| 岳西县| 桃源县| 苏尼特右旗| 车险| 马尔康县| 莫力| 资兴市| 彰化市| 温宿县| 五莲县| 衢州市| 丹江口市| 伊通| 米易县| 西和县| 平果县| 和田县| 垣曲县| 溧水县| 龙陵县| 伊宁市| 平度市| 阳西县| 涞水县| 三河市| 花莲县| 牙克石市| 大理市|