欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于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 連接始終打開)。

因此,工程師們一直在思考,有沒(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)聽窗口關(guān)閉事件,當(dāng)窗口關(guān)閉時(shí),主動(dòng)去關(guān)閉websocket連接,防止連接還沒(mé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è)類。

package com.sun.web.handler;
 
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
 
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
 
/**
 * @ServerEndpoint 注解是一個(gè)類層次的注解,它的功能主要是將目前的類定義成一個(gè)websocket服務(wù)器端,
 * 注解的值將被用于監(jiān)聽用戶連接的終端訪問(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)文章

  • 詳解SpringIOC容器中bean的作用范圍和生命周期

    詳解SpringIOC容器中bean的作用范圍和生命周期

    這篇文章主要介紹了SpringIOC容器中bean的作用范圍和生命周期,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Java解決前端數(shù)據(jù)處理及亂碼問(wèn)題

    Java解決前端數(shù)據(jù)處理及亂碼問(wèn)題

    大伙們有沒(méi)有遇到數(shù)據(jù)亂碼的問(wèn)題,真的是讓人心情煩躁,今天就來(lái)教下大家數(shù)據(jù)怎么傳輸?shù)角岸艘约皝y碼問(wèn)題怎么解決的,需要的朋友可以參考一下
    2021-12-12
  • 淺析Java類和數(shù)據(jù)結(jié)構(gòu)中常用的方法

    淺析Java類和數(shù)據(jù)結(jié)構(gòu)中常用的方法

    下面小編就為大家?guī)?lái)一篇淺析Java類和數(shù)據(jù)結(jié)構(gòu)中常用的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • 基于SpringMVC中的路徑參數(shù)和URL參數(shù)實(shí)例

    基于SpringMVC中的路徑參數(shù)和URL參數(shù)實(shí)例

    這篇文章主要介紹了基于SpringMVC中的路徑參數(shù)和URL參數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • java中對(duì)list分頁(yè)并顯示數(shù)據(jù)到頁(yè)面實(shí)例代碼

    java中對(duì)list分頁(yè)并顯示數(shù)據(jù)到頁(yè)面實(shí)例代碼

    這篇文章主要介紹了java中對(duì)list分頁(yè)并顯示數(shù)據(jù)到頁(yè)面實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • gson對(duì)象序列化的示例

    gson對(duì)象序列化的示例

    本文介紹如何將Java對(duì)象序列化為Json文件,然后讀取該Json文件讀取回Java對(duì)象。在下面的示例中,我們創(chuàng)建了一個(gè)Student類。然后生成一個(gè)student.json文件,該文件將具有Student對(duì)象的json數(shù)據(jù)。
    2020-11-11
  • BeanUtils.copyProperties復(fù)制不生效的解決

    BeanUtils.copyProperties復(fù)制不生效的解決

    這篇文章主要介紹了BeanUtils.copyProperties復(fù)制不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java通過(guò)Socket實(shí)現(xiàn)簡(jiǎn)單多人聊天室

    Java通過(guò)Socket實(shí)現(xiàn)簡(jiǎn)單多人聊天室

    這篇文章主要為大家詳細(xì)介紹了Java通過(guò)Socket實(shí)現(xiàn)簡(jiǎn)單多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • Java集合類知識(shí)點(diǎn)總結(jié)

    Java集合類知識(shí)點(diǎn)總結(jié)

    本文把Java集合類的相關(guān)知識(shí)點(diǎn)做了總結(jié),并把Java常用集合類之間的區(qū)別做了分析,一起參考學(xué)習(xí)下。
    2018-02-02
  • Spring Mybatis Mapper模糊查詢的幾種方法

    Spring Mybatis Mapper模糊查詢的幾種方法

    在Spring結(jié)合Mybatis進(jìn)行開發(fā)時(shí),實(shí)現(xiàn)模糊查詢是一個(gè)常見需求,在Mybatis中,LIKE查詢可以通過(guò)多種方式實(shí)現(xiàn),本文給大家介紹了Spring Mybatis Mapper模糊查詢的幾種方法,需要的朋友可以參考下
    2024-03-03

最新評(píng)論