国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

用OkHttp實(shí)現(xiàn)WebSocket長(zhǎng)連接

開(kāi)發(fā) 前端
先簡(jiǎn)單介紹下WebSocket。我們都知道Http是處于應(yīng)用層的一個(gè)通信協(xié)議,但是只支持單向主動(dòng)通信,做不到服務(wù)器主動(dòng)向客戶端推送消息。而且Http是無(wú)狀態(tài)的,即每次通信都沒(méi)有關(guān)聯(lián)性,導(dǎo)致跟服務(wù)器關(guān)系不緊密。

今天給大家?guī)?lái)一篇老文章,介紹WebSocket,大家可以了解了解。

前言

最近老板又來(lái)新需求了,要做一個(gè)物聯(lián)網(wǎng)相關(guān)的app,其中有個(gè)需求是客戶端需要收發(fā)服務(wù)器不定期發(fā)出的消息。

內(nèi)心OS:

  • 這咋整呢?通過(guò)接口輪詢?定時(shí)訪問(wèn)接口,有數(shù)據(jù)就更新?
  • 不行不行,這樣浪費(fèi)資源了,還耗電,會(huì)導(dǎo)致很多請(qǐng)求都是無(wú)效的網(wǎng)絡(luò)操作。
  • 那就長(zhǎng)連接唄?WebSocket協(xié)議好像不錯(cuò),通過(guò)握手建立長(zhǎng)連接后,可以隨時(shí)收發(fā)服務(wù)器的消息。那就它了!
  • 怎么集成呢?正好前段時(shí)間復(fù)習(xí)OkHttp源碼的時(shí)候發(fā)現(xiàn)了它是支持Websocket協(xié)議的,那就用它試試吧!

開(kāi)淦!

WebSocket介紹

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

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

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

這里貼上請(qǐng)求頭和響應(yīng)頭信息,從網(wǎng)上找了一張圖:

3851594110877_.pic.jpg

 

簡(jiǎn)單說(shuō)明下參數(shù):

  • URL一般是以ws或者wss開(kāi)頭,ws對(duì)應(yīng)Websocket協(xié)議,wss對(duì)應(yīng)在TLS之上的WebSocket。類似于Http和Https的關(guān)系。
  • 請(qǐng)求方法為GET方法。
  • Connection:Upgrade,表示客戶端要連接升級(jí),不用Http協(xié)議。
  • Upgrade:websocket, 表示客戶端要升級(jí)建立Websocket連接。
  • Sec-Websocket-Key:key, 這個(gè)key是隨機(jī)生成的,服務(wù)器會(huì)通過(guò)這個(gè)參數(shù)驗(yàn)證該請(qǐng)求是否有效。
  • Sec-WebSocket-Version:13, websocket使用的協(xié)議,一般就是13。
  • Sec-webSocket-Extension:permessage-deflate,客戶端指定的一些擴(kuò)展協(xié)議,比如這里permessage-deflate就是WebSocket的一種壓縮協(xié)議。
  • 響應(yīng)碼101,表示響應(yīng)協(xié)議升級(jí),后續(xù)的數(shù)據(jù)交互都按照Upgradet指定的WebSocket協(xié)議來(lái)。

OkHttp實(shí)現(xiàn)

添加OkHttp依賴

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

實(shí)現(xiàn)代碼

首先是初始化OkHttpClient和WebSocket實(shí)例:

  1. /** 
  2.  * 初始化WebSocket 
  3.  */ 
  4. public void init() { 
  5.     mWbSocketUrl = "ws://echo.websocket.org"
  6.     mClient = new OkHttpClient.Builder() 
  7.             .pingInterval(10, TimeUnit.SECONDS) 
  8.             .build(); 
  9.     Request request = new Request.Builder() 
  10.             .url(mWbSocketUrl) 
  11.             .build(); 
  12.     mWebSocket = mClient.newWebSocket(request, new WsListener()); 

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

這里要注意的點(diǎn)是pingInterval方法的配置,這個(gè)方法主要是用來(lái)設(shè)置WebSocket連接的保活。相信做過(guò)長(zhǎng)連接的同學(xué)都知道,一個(gè)長(zhǎng)連接一般要隔幾秒發(fā)送一條消息告訴服務(wù)器我在線,而服務(wù)器也會(huì)回復(fù)一個(gè)消息表示收到了,這樣就確認(rèn)了連接正常,客戶端和服務(wù)器端都在線。

如果服務(wù)器沒(méi)有按時(shí)收到這個(gè)消息那么服務(wù)器可能就會(huì)主動(dòng)關(guān)閉這個(gè)連接,節(jié)約資源。客戶端沒(méi)有正常收到這個(gè)返回的消息,也會(huì)做一些類似重連的操作,所以這個(gè)保活消息非常重要。

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

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

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

  1. //監(jiān)聽(tīng)事件,用于收消息,監(jiān)聽(tīng)連接的狀態(tài) 
  2. class WsListener extends WebSocketListener { 
  3.     @Override 
  4.     public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) { 
  5.         super.onClosed(webSocket, code, reason); 
  6.     } 
  7.  
  8.     @Override 
  9.     public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) { 
  10.         super.onClosing(webSocket, code, reason); 
  11.     } 
  12.  
  13.     @Override 
  14.     public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) { 
  15.         super.onFailure(webSocket, t, response); 
  16.     } 
  17.  
  18.     @Override 
  19.     public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) { 
  20.         super.onMessage(webSocket, text); 
  21.         Log.e(TAG, "客戶端收到消息:" + text); 
  22.         onWSDataChanged(DATE_NORMAL, text); 
  23.        //測(cè)試發(fā)消息 
  24.         webSocket.send("我是客戶端,你好啊"); 
  25.     } 
  26.  
  27.     @Override 
  28.     public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) { 
  29.         super.onMessage(webSocket, bytes); 
  30.     } 
  31.  
  32.     @Override 
  33.     public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) { 
  34.         super.onOpen(webSocket, response); 
  35.         Log.e(TAG,"連接成功!"); 
  36.     } 
  37.  
  38.  
  39. //發(fā)送String消息 
  40. public void send(final String message) { 
  41.     if (mWebSocket != null) { 
  42.         mWebSocket.send(message); 
  43.     } 
  44.  
  45. /** 
  46.  * 發(fā)送byte消息 
  47.  * @param message 
  48.  */ 
  49. public void send(final ByteString message) { 
  50.     if (mWebSocket != null) { 
  51.         mWebSocket.send(message); 
  52.     } 
  53. }     
  54.  
  55. //主動(dòng)斷開(kāi)連接 
  56. public void disconnect(int code, String reason) { 
  57.     if (mWebSocket != null
  58.         mWebSocket.close(code, reason); 

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

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

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

  • send(text: String)發(fā)送一個(gè)String類型的消息
  • send(bytes: ByteString) 發(fā)送一個(gè)二進(jìn)制類型的消息
  • close(code: Int, reason: String?)關(guān)閉WebSocket連接

如果有同學(xué)想測(cè)試下WebSocket的功能但是又沒(méi)有實(shí)際的服務(wù)器,怎么辦呢?其實(shí)OkHttp官方有一個(gè)MockWebSocket服務(wù),可以用來(lái)模擬服務(wù)端,下面我們一起試一下:

模擬服務(wù)器

首先集成MockWebSocket服務(wù)庫(kù):

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

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

  1. MockWebServer mMockWebServer = new MockWebServer(); 
  2.   MockResponse response = new MockResponse() 
  3.           .withWebSocketUpgrade(new WebSocketListener() { 
  4.               @Override 
  5.               public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) { 
  6.                   super.onOpen(webSocket, response); 
  7.                   //有客戶端連接時(shí)回調(diào) 
  8.                   Log.e(TAG, "服務(wù)器收到客戶端連接成功回調(diào):"); 
  9.                   mWebSocket = webSocket; 
  10.                   mWebSocket.send("我是服務(wù)器,你好呀"); 
  11.               } 
  12.  
  13.               @Override 
  14.               public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) { 
  15.                   super.onMessage(webSocket, text); 
  16.  
  17.                   Log.e(TAG, "服務(wù)器收到消息:" + text); 
  18.               } 
  19.  
  20.               @Override 
  21.               public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) { 
  22.                   super.onClosed(webSocket, code, reason); 
  23.                   Log.e(TAG, "onClosed:"); 
  24.               } 
  25.           }); 
  26.  
  27.   mMockWebServer.enqueue(response); 

這里服務(wù)器端在收到客戶端連接成功消息后,給客戶端發(fā)送了一條消息。要注意的是這段代碼要在子線程執(zhí)行,因?yàn)橹骶€程不能進(jìn)行網(wǎng)絡(luò)操作。

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

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

ok,運(yùn)行項(xiàng)目

//運(yùn)行結(jié)果 E/jimu: mWbSocketUrl=ws://localhost:38355/ E/jimu: 服務(wù)器收到客戶端連接成功回調(diào): E/jimu: 連接成功! E/jimu: 客戶端收到消息:我是服務(wù)器,你好呀 E/jimu: 服務(wù)器收到消息:我是客戶端,你好啊

參考

https://github.com/square/okhttp

本文轉(zhuǎn)載自微信公眾號(hào)「碼上積木,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系碼上積木公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 碼上積木
相關(guān)推薦

2020-03-19 10:13:13

OkHttpWebSocket

2025-01-27 12:31:23

PythonLocustWebSocket

2017-07-11 13:58:10

WebSocket

2021-07-30 15:06:05

鴻蒙HarmonyOS應(yīng)用

2024-01-11 08:53:58

2021-04-27 18:12:22

WebSocket持久化連接HTTP

2018-06-06 11:01:25

HTTP長(zhǎng)連接短連接

2022-10-24 08:14:35

長(zhǎng)連接負(fù)載均衡Conusmer

2022-12-02 13:49:41

2023-11-28 08:49:01

短輪詢WebSocket長(zhǎng)輪詢

2023-01-27 23:31:08

數(shù)據(jù)長(zhǎng)輪詢長(zhǎng)連接

2020-03-24 15:15:29

HttpClientOkHttpJava

2021-03-24 09:06:01

MySQL長(zhǎng)連接短連接

2024-06-06 09:12:40

數(shù)據(jù)庫(kù)SQLServer

2015-06-11 10:57:10

2023-12-04 07:14:40

通信微服務(wù)

2021-11-16 10:45:35

WebSocketWebShellLinux

2023-08-14 08:01:12

websocket8g用戶

2021-03-25 08:29:33

SpringBootWebSocket即時(shí)消息

2020-09-05 17:00:20

HTTP長(zhǎng)連接短連接
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

丰满少妇被猛烈进入高清播放| 区一区二日本| 欧美艳星brazzers| 一区二区三区视频在线播放| 涩爱av色老久久精品偷偷鲁| 日韩av一区二区三区| 色综合伊人色综合网站| 欧美一区二区视频17c| 日韩一区网站| 日韩电影网在线| 巨骚激情综合| 国产亚洲成av人在线观看导航| 欧美不卡福利| 日本成人在线播放| 最新国产の精品合集bt伙计| 精品国产一区二区三区在线| 国模精品视频| 欧美日韩中文字幕| 国产精品欧美激情| 黑人巨大精品欧美一区二区桃花岛| 日韩高清在线不卡| 亚洲国产女人aaa毛片在线| 91亚洲精品丁香在线观看| 国产免费区一区二区三视频免费 | 亚洲黄色小视频在线观看| 日韩有码一区二区三区| 亚洲精品免费av| 日本在线中文字幕一区| 亚洲精选在线视频| 黄色一级片播放| 黑人巨大精品欧美一区| 中文字幕日韩欧美| 中文字幕无码不卡免费视频| 久久成人av少妇免费| 久草热久草热线频97精品| а√天堂8资源在线官网| 亚洲3atv精品一区二区三区| 奇米777影视成人四色| 欧美国产欧美亚州国产日韩mv天天看完整| 欧美国产日本高清在线| 成人免费看黄| 国产亚洲精品久久久久久牛牛| 毛片在线网址| 精品国产凹凸成av人导航| 色婷婷777777仙踪林| 午夜在线a亚洲v天堂网2018| 大波视频国产精品久久| 欧美精品综合| 精品欧美一区二区在线观看视频 | 亚洲精选视频在线| sihu成人| 欧美久久精品一级c片| 91国在线精品国内播放| 国产黄色在线播放| 色综合久久综合网97色综合 | 久久久精品一区二区毛片免费看| 亚洲精品福利视频| 成人短视频app| 中文欧美在线视频| 国产精品视频一区二区三区| 色与欲影视天天看综合网| 91九色porny在线| 亚洲二区在线观看| 高清av在线| 欧美精品一区二区在线播放| 波多野结衣亚洲一二三| 欧美激情亚洲综合一区| 国产毛片在线| 欧美日韩1234| 国产又粗又长又大的视频| 精品国产一区二区三区四区| 国产精品美女免费| 亚洲午夜伦理| 特级毛片在线免费观看| 久久久噜噜噜久久中文字幕色伊伊 | 99re成人精品视频| 99re99| 欧美午夜精品久久久久久人妖| 一区二区高清不卡| 久久青草欧美一区二区三区| av五月天在线| 欧美日韩精品在线观看| 丁香花高清在线观看完整版| 九九精品视频在线| 欧美日韩综合| 天天干天天色天天爽| 中文字幕制服丝袜成人av| 春暖花开成人亚洲区| 国产精品国产自产拍在线| h网站在线播放| 91精品国产色综合久久ai换脸 | 精品国产欧美一区二区五十路 | 九一免费在线观看| 成人免费一区二区三区视频| 国外av在线| 亚洲午夜精品久久久久久久久久久久| 精品福利一区| 女女同性女同一区二区三区91| gay欧美网站| 国产精品人成电影在线观看| 亚洲精品亚洲人成在线| zzijzzij亚洲日本少妇熟睡| 欧美极品少妇xxxxⅹ裸体艺术| 日韩精品一区二区三区免费观看| 日韩精品亚洲精品| 91亚洲无吗| 久久久久久国产精品mv| 成人黄色小视频在线观看| 污香蕉视频在线观看| 国产欧美一区二区精品忘忧草 | 日韩精品欧美精品| 天天干天天操天天玩| 激情国产一区二区| 精品伦理一区二区| 中文字幕v亚洲ⅴv天堂| 日韩午夜免费| 亚洲国产专区校园欧美| 国产精品露出视频| 夜夜嗨网站十八久久| 韩国精品视频在线观看| 3344国产永久在线观看视频| 成年人视频大全| 国产精品久久婷婷六月丁香| 久久久久久久综合色一本| 亚洲综合婷婷| 免费视频爱爱太爽了| 欧美日韩在线免费视频| 香港欧美日韩三级黄色一级电影网站| 国产三级三级看三级| 久久一区二区三区av| 国产成人无码精品久久久性色| 在线观看高清av| 理论片午夜视频在线观看| 色婷婷av一区| xxxx69视频| 91精品国产成人www| 久久久电影一区二区三区| 欧美一区二区三区婷婷| 欧美日韩国产色视频| 日本一区二区三区视频在线看 | 韩国中文字幕av| 久久精品美女视频网站| 久久色.com| 欧美日日夜夜| 日产精品久久久久久久性色| 成人欧美一区二区三区黑人免费| 色素色在线综合| 国内成人免费视频| 久久综合国产| hd国产人妖ts另类视频| 91黑丝在线| 一区二区在线视频播放| 成人免费淫片aa视频免费| 久久久天堂av| 日韩啪啪电影网| 日韩成人精品一区二区| 99久久精品免费| 久久99国产精品久久99| 国产丶欧美丶日本不卡视频| 蜜桃传媒av| 蜜桃视频在线观看91| 亚洲精品久久区二区三区蜜桃臀| 日韩在线观看网站| 亚洲国产日韩精品| 久久综合久久综合久久| 欧美激情网址| 国产欧美久久久久久久久| 黄色片网址在线观看| 欧美色图另类小说| 91精品国产福利在线观看| 玖草视频在线| 欧美日韩国产免费观看视频| 九九久久电影| 午夜一区二区三视频在线观看| 久久精品视频免费看| 91色精品视频在线| 日韩视频一区二区三区在线播放免费观看| 男人在线视频资源| 国产精品6699| 一区二区毛片| 日韩免费一区二区| av影院在线免费观看| 二级片在线观看| 中文字幕日韩欧美在线视频| 91免费看片在线观看| 国语一区二区三区| 午夜影院韩国伦理在线| 91偷拍精品一区二区三区| 日韩限制级电影在线观看| 精品一区二区三区在线观看| 色综合.com| 亚洲伦理电影| 免费亚洲一区二区| 色偷偷av亚洲男人的天堂| 自拍偷在线精品自拍偷无码专区| 久久久久久影院| 亚洲精品88| 91精品国产高久久久久久五月天| 国产精品视频在线免费观看 | 欧美另类极品|