本平臺的文章更新會有延遲,你們能夠關注微信公衆號-顧林海,包括年末前會更新kotlin由淺入深系列教程,目前計劃在微信公衆號進行首發,若是你們想獲取最新教程,請關注微信公衆號,謝謝!java
在講解如何利用OkHttp實現WebSocket以前,咱們聊聊輪詢技術,什麼是輪詢?輪詢就是在特定的時間間隔,由瀏覽器對服務器發出HTTP請求,而後由服務器返回最新的數據給客戶端的瀏覽器。web
輪詢分爲兩種:瀏覽器
短輪詢:經過不斷的向服務端發送數據,客戶端發送Request,服務端直接返回Response(無論服務端數據有沒有改變)。服務器
長輪詢:經過不斷的向服務端發送數據,客戶端發送Request,服務端發現數據沒有改變,就將這個Request掛起,直到有最新數據再發送Response給客戶端。微信
經過上面短輪詢的介紹,不難發現它的缺點,若是在某段時間內,服務端數據沒有任何變化,但客戶端仍是不停的發送請求給服務端,服務端也無論數據是否變化,直接返回結果給客戶端,那麼在這段時間內的全部請求實際上是無效的。網絡
這個時候長輪詢就彌補了短輪詢的缺點,客戶端發送請求,服務器會查詢數據是否更新,沒有更新就會掛起這個請求,直到有新數據,服務端纔會把Response返回給客戶端,這樣是否是就完美了?其實不是,服務端將客戶端的請求掛起會致使資源的浪費,好比有1W人請求服務端,那這個時候服務端這邊就要開啓1W個線程,致使資源佔用。異步
不管是使用短輪詢仍是使用長輪詢,它們通訊的方式仍是經過HTTP請求的,HTTP頭部比較大,但實際數據比較少,形成帶寬的浪費,因爲不停的輪詢,致使服務器CPU佔用太高。ide
既然短輪詢和長輪詢有這麼多問題,那有沒有什麼解決方案呢?這時WebSocket登場,看下面這張圖(來源網絡)。ui
能夠看到WebSocket的鏈接是長期存在的,而且能夠不斷的進行通訊,這是一個全雙工的通訊模式,客戶端能夠不停的向服務端發送消息,服務端也能夠不停的發送消息給客戶端。url
那麼WebSocket和HTTP有什麼區別呢?HTTP是一個Request對應一個Response,就是說客服發送一個請求,服務端接受到請求才會向客戶端發送響應,Request和Response是一對一的關係,服務端比較懶,它必定要客戶端給它發送請求,服務端纔會有響應。相比而言,WebSocket在客戶端與服務端創建鏈接後,客服端與服務端就能夠進行全雙工通訊了,WebSocket在創建鏈接時也是用到了HTTP的協議,但創建起鏈接後,雙方的通訊與HTTP就沒有任何關係了。
繼續下個問題,WebSocket與Socket有什麼關係?Socket並非一種協議,它只是方便咱們使用TCP或UDP抽象出來的一層,它是應用層和傳輸層之間的一種接口,而WebSocket是一種協議,總的來講,這二者壓根沒有任何關係。
總結:WebSocket是協議,是一個基於TCP的協議,爲了創建一個WebSocket鏈接,須要向服務器發起一個HTTP請求,並加入頭部信息「Upgrade:WebSocket」,服務器會解析這些附加的頭信息,同時產生Response給客戶端,這樣客戶端與服務端之間的WebSocket連接就鏈接起來了。
接下來就來介紹OkHttp中怎麼使用WebSocket。實例代碼以下:
private OkHttpClient mOkHttpClient;
private void webSocketConnect() {
mOkHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://192.168.1.1")
.build();
ClientWebSocketListener listener=new ClientWebSocketListener();
mOkHttpClient.newWebSocket(request,listener);
mOkHttpClient.dispatcher().executorService().shutdown();
}
複製代碼
既然使用的是OkHttp,那麼第一步就得建立OkHttpClient對象,第二步建立Request對象,並設置url地址,第三步建立一個Listener,這個Listener用於客戶端與服務端之間的異步通知,第三步經過OkHttpClient的newWebSocket方法創建客服端與服務端之間的鏈接,最後關閉Dispatcher當中的線程池。
ClientWebSocketListener代碼以下:
private WebSocket mWebSocket;
private final class ClientWebSocketListener extends WebSocketListener{
@Override
public void onOpen(WebSocket webSocket, Response response) {
mWebSocket=webSocket;
mWebSocket.send("您好,我是客戶端");
}
@Override
public void onMessage(WebSocket webSocket, String text) {
Message message=Message.obtain();
message.obj=text;
mWebSocketHandler.sendMessage(message);
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
Message message=Message.obtain();
message.obj=bytes.utf8();
mWebSocketHandler.sendMessage(message);
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
if(null!=mWebSocket){
mWebSocket.close(1000,"再見");
mWebSocket=null;
}
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, @javax.annotation.Nullable Response response) {
}
}
複製代碼
ClientWebSocketListener繼承自WebSocketListener接口,並實現該接口中的一些方法。
onOpen方法實在客戶端與服務端創建鏈接時的回調,能夠經過WebSocket的send方法向服務端發送消息,因爲OkHttp使用的是本身的後臺發送數據,因此在send的時候不用擔憂會阻塞當前線程。
兩個onMessage方法,只是傳入類型不一樣,能夠在這邊獲取服務端發送過來的消息,onMessage運行在工做線程,若是須要和UI線程進行交互,就得使用Handler來發送消息給UI線程。
onClosing方法表示服務端再也不發送數據給客戶端時的回調,準備關閉鏈接,咱們能夠在這個方法中關閉WebSocket鏈接。
onClosed方法表示已經被徹底關閉了,這時候回調這個方法。onFailure方法在鏈接失敗的時候會回調這個方法。
搜索微信「顧林海」公衆號,按期推送優質文章。