美文网首页Android技术知识Android开发经验谈Android文章
Android小知识-利用OkHttp实现WebSocket通信

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

作者: 爱读书的顾先生 | 来源:发表于2018-10-29 09:25 被阅读950次

    本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,包括年底前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,如果大家想获取最新教程,请关注微信公众号,谢谢!

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

    轮询分为两种:

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

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

    通过上面短轮询的介绍,不难发现它的缺点,如果在某段时间内,服务端数据没有任何变化,但客户端还是不停的发送请求给服务端,服务端也不管数据是否变化,直接返回结果给客户端,那么在这段时间内的所有请求其实是无效的。

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

    无论是使用短轮询还是使用长轮询,它们通信的方式还是通过HTTP请求的,HTTP头部比较大,但实际数据比较少,造成带宽的浪费,由于不停的轮询,导致服务器CPU占用过高。

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

    image

    可以看到WebSocket的连接是长期存在的,并且可以不断的进行通信,这是一个全双工的通信模式,客户端可以不停的向服务端发送消息,服务端也可以不停的发送消息给客户端。

    那么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

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

    相关文章

      网友评论

        本文标题:Android小知识-利用OkHttp实现WebSocket通信

        本文链接:https://www.haomeiwen.com/subject/vtwvtqtx.html