Android小知识-利用OkHttp实现WebSocket通讯

本平台的文章更新会有延迟,你们能够关注微信公众号-顾林海,包括年末前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,若是你们想获取最新教程,请关注微信公众号,谢谢!java

在讲解如何利用OkHttp实现WebSocket以前,咱们聊聊轮询技术,什么是轮询?轮询就是在特定的时间间隔,由浏览器对服务器发出HTTP请求,而后由服务器返回最新的数据给客户端的浏览器。web

轮询分为两种:浏览器

  1. 短轮询:经过不断的向服务端发送数据,客户端发送Request,服务端直接返回Response(无论服务端数据有没有改变)。服务器

  2. 长轮询:经过不断的向服务端发送数据,客户端发送Request,服务端发现数据没有改变,就将这个Request挂起,直到有最新数据再发送Response给客户端。微信

经过上面短轮询的介绍,不难发现它的缺点,若是在某段时间内,服务端数据没有任何变化,但客户端仍是不停的发送请求给服务端,服务端也无论数据是否变化,直接返回结果给客户端,那么在这段时间内的全部请求实际上是无效的。网络

这个时候长轮询就弥补了短轮询的缺点,客户端发送请求,服务器会查询数据是否更新,没有更新就会挂起这个请求,直到有新数据,服务端才会把Response返回给客户端,这样是否是就完美了?其实不是,服务端将客户端的请求挂起会致使资源的浪费,好比有1W人请求服务端,那这个时候服务端这边就要开启1W个线程,致使资源占用。异步

不管是使用短轮询仍是使用长轮询,它们通讯的方式仍是经过HTTP请求的,HTTP头部比较大,但实际数据比较少,形成带宽的浪费,因为不停的轮询,致使服务器CPU占用太高。ide

既然短轮询和长轮询有这么多问题,那有没有什么解决方案呢?这时WebSocket登场,看下面这张图(来源网络)。ui

image

能够看到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方法在链接失败的时候会回调这个方法。


838794-506ddad529df4cd4.webp.jpg

搜索微信“顾林海”公众号,按期推送优质文章。

相关文章
相关标签/搜索