1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關咨詢
      選擇下列產品馬上在線溝通
      服務時間:8:30-17:00
      你可能遇到了下面的問題
      關閉右側工具欄

      新聞中心

      這里有您想知道的互聯(lián)網營銷解決方案
      WebSocket中怎么利用OkHttp實現(xiàn)長連接

      WebSocket中怎么利用OkHttp實現(xiàn)長連接,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

      網站建設哪家好,找成都創(chuàng)新互聯(lián)!專注于網頁設計、網站建設、微信開發(fā)、微信小程序定制開發(fā)、集團企業(yè)網站建設等服務項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了山東免費建站歡迎大家使用!

      WebSocket介紹

      先簡單介紹下WebSocket。我們都知道Http是處于應用層的一個通信協(xié)議,但是只支持單向主動通信,做不到服務器主動向客戶端推送消息。而且Http是無狀態(tài)的,即每次通信都沒有關聯(lián)性,導致跟服務器關系不緊密。

      為了解決和服務器長時間通信的痛點呢,HTML5規(guī)范引出了WebSocket協(xié)議(知道這名字咋來的吧,人家HTML5規(guī)范引出的,隨爸姓),是一種建立在TCP協(xié)議基礎上的全雙工通信的協(xié)議。他跟Http同屬于應用層協(xié)議,下層還是需要通過TCP建立連接。

      但是,WebSocket在TCP連接建立后,還要通過Http進行一次握手,也就是通過Http發(fā)送一條GET請求消息給服務器,告訴服務器我要建立WebSocket連接了,你準備好哦,具體做法就是在頭部信息中添加相關參數。然后服務器響應我知道了,并且將連接協(xié)議改成WebSocket,開始建立長連接。

      這里貼上請求頭和響應頭信息,從網上找了一張圖:

      WebSocket中怎么利用OkHttp實現(xiàn)長連接

      3851594110877_.pic.jpg

      簡單說明下參數:

      • URL一般是以ws或者wss開頭,ws對應Websocket協(xié)議,wss對應在TLS之上的WebSocket。類似于Http和Https的關系。

      • 請求方法為GET方法。

      • Connection:Upgrade,表示客戶端要連接升級,不用Http協(xié)議。

      • Upgrade:websocket, 表示客戶端要升級建立Websocket連接。

      • Sec-Websocket-Key:key, 這個key是隨機生成的,服務器會通過這個參數驗證該請求是否有效。

      • Sec-WebSocket-Version:13, websocket使用的協(xié)議,一般就是13。

      • Sec-webSocket-Extension:permessage-deflate,客戶端指定的一些擴展協(xié)議,比如這里permessage-deflate就是WebSocket的一種壓縮協(xié)議。

      • 響應碼101,表示響應協(xié)議升級,后續(xù)的數據交互都按照Upgradet指定的WebSocket協(xié)議來。

      OkHttp實現(xiàn)

      添加OkHttp依賴

      implementation("com.squareup.okhttp3:okhttp:4.7.2")

      實現(xiàn)代碼

      首先是初始化OkHttpClient和WebSocket實例:

      /**  * 初始化WebSocket  */ public void init() {     mWbSocketUrl = "ws://echo.websocket.org";     mClient = new OkHttpClient.Builder()             .pingInterval(10, TimeUnit.SECONDS)             .build();     Request request = new Request.Builder()             .url(mWbSocketUrl)             .build();     mWebSocket = mClient.newWebSocket(request, new WsListener()); }

      這里主要是配置了OkHttp的一些參數,以及WebSocket的連接地址。其中newWebSocket方法就是進行WebSocket的初始化和連接。

      這里要注意的點是pingInterval方法的配置,這個方法主要是用來設置WebSocket連接的保活。相信做過長連接的同學都知道,一個長連接一般要隔幾秒發(fā)送一條消息告訴服務器我在線,而服務器也會回復一個消息表示收到了,這樣就確認了連接正常,客戶端和服務器端都在線。

      如果服務器沒有按時收到這個消息那么服務器可能就會主動關閉這個連接,節(jié)約資源。客戶端沒有正常收到這個返回的消息,也會做一些類似重連的操作,所以這個保活消息非常重要。

      我們稱這個消息叫作心跳包,一般用PING,PONG表示,像乒乓球一樣,一來一回。所以這里的pingInterval就是設置心跳包發(fā)送的間隔時間,設置了這個方法之后,OkHttp就會自動幫我們發(fā)送心跳包事件,也就是ping包。當間隔時間到了,沒有收到pong包的話,監(jiān)聽事件中的onFailure方法就會被調用,此時我們就可以進行重連。

      但是由于實際業(yè)務需求不一樣,以及okhttp中心跳包事件給予我們權限較少,所以我們也可以自己完成心跳包事件,即在WebSocket連接成功之后,開始定時發(fā)送ping包,在下一次發(fā)送ping包之前檢查上一個pong包是否收到,如果沒收到,就視為異常,開始重連。感興趣的同學可以看看文末的相關源碼。

      建立連接后,我們就可以正常發(fā)送和讀取消息了,也就是在上文WsListener監(jiān)聽事件中表現(xiàn):

      //監(jiān)聽事件,用于收消息,監(jiān)聽連接的狀態(tài) class WsListener extends WebSocketListener {     @Override     public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {         super.onClosed(webSocket, code, reason);     }      @Override     public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) {         super.onClosing(webSocket, code, reason);     }      @Override     public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {         super.onFailure(webSocket, t, response);     }      @Override     public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {         super.onMessage(webSocket, text);         Log.e(TAG, "客戶端收到消息:" + text);         onWSDataChanged(DATE_NORMAL, text);        //測試發(fā)消息         webSocket.send("我是客戶端,你好啊");     }      @Override     public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) {         super.onMessage(webSocket, bytes);     }      @Override     public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {         super.onOpen(webSocket, response);         Log.e(TAG,"連接成功!");     } }   //發(fā)送String消息 public void send(final String message) {     if (mWebSocket != null) {         mWebSocket.send(message);     } }  /**  * 發(fā)送byte消息  * @param message  */ public void send(final ByteString message) {     if (mWebSocket != null) {         mWebSocket.send(message);     } }      //主動斷開連接 public void disconnect(int code, String reason) {     if (mWebSocket != null)         mWebSocket.close(code, reason); }

      這里要注意,回調的方法都是在子線程回調的,如果需要更新UI,需要切換到主線程。

      基本操作就這么多,還是很簡單的吧,初始化Websocket——連接——連接成功——收發(fā)消息。

      其中WebSocket類是一個操作接口,主要提供了以下幾個方法

      • send(text: String)發(fā)送一個String類型的消息

      • send(bytes: ByteString) 發(fā)送一個二進制類型的消息

      • close(code: Int, reason: String?)關閉WebSocket連接

      如果有同學想測試下WebSocket的功能但是又沒有實際的服務器,怎么辦呢?其實OkHttp官方有一個MockWebSocket服務,可以用來模擬服務端,下面我們一起試一下:

      模擬服務器

      首先集成MockWebSocket服務庫:

      implementation 'com.squareup.okhttp3:mockwebserver:4.7.2'

      然后就可以新建MockWebServer,并加入MockResponse作為接收消息的響應。

      MockWebServer mMockWebServer = new MockWebServer();   MockResponse response = new MockResponse()           .withWebSocketUpgrade(new WebSocketListener() {               @Override               public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {                   super.onOpen(webSocket, response);                   //有客戶端連接時回調                   Log.e(TAG, "服務器收到客戶端連接成功回調:");                   mWebSocket = webSocket;                   mWebSocket.send("我是服務器,你好呀");               }                @Override               public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {                   super.onMessage(webSocket, text);                    Log.e(TAG, "服務器收到消息:" + text);               }                @Override               public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {                   super.onClosed(webSocket, code, reason);                   Log.e(TAG, "onClosed:");               }           });    mMockWebServer.enqueue(response);

      這里服務器端在收到客戶端連接成功消息后,給客戶端發(fā)送了一條消息。要注意的是這段代碼要在子線程執(zhí)行,因為主線程不能進行網絡操作。

      然后就可以去初始化Websocket客戶端了:

      //獲取連接url,初始化websocket客戶端 String websocketUrl = "ws://" + mMockWebServer.getHostName() + ":" + mMockWebServer.getPort() + "/"; WSManager.getInstance().init(websocketUrl);

      看完上述內容,你們掌握WebSocket中怎么利用OkHttp實現(xiàn)長連接的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!


      分享文章:WebSocket中怎么利用OkHttp實現(xiàn)長連接
      URL鏈接:http://ef60e0e.cn/article/gcodoj.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        牟定县| 张家港市| 株洲市| 四会市| 盐津县| 屏东市| 桃源县| 双鸭山市| 罗源县| 屯留县| 津南区| 涿鹿县| 建水县| 壤塘县| 阳城县| 禄丰县| 凤山市| 襄城县| 伊吾县| 兴文县| 台南县| 深泽县| 政和县| 监利县| 东阳市| 遵义县| 襄城县| 阳东县| 含山县| 砀山县| 义马市| 淮滨县| 南溪县| 全州县| 牙克石市| 蒙山县| 长宁县| 榆树市| 汉川市| 英德市| 陆川县|