深入浅出 OkHttp Websocket-- 使用篇

20,523 阅读3分钟

说起okhttp,想必各位老司机们一定都不会陌生,但是okhttp还可以进行websocket通信你造吗?下面就让我们一起来深入浅出okhttp websocket吧!

OkHttp Websocket

首先我们先明确一下要实现的效果:

  1. 客户端与服务端建连
  2. 客户端向服务端发送消息
  3. 服务端在接受消息后以“response-接受的消息内容“的形式返回给客户端
  4. 当服务端收到第5条信息的时候,主动关闭与客户端的连接

引入依赖库

为了方便我们客户端进行websocket的测试,okhttp还为大伙提供了扩展模块mockserver来模拟服务端。

(需要注意的是低版本的okhttp还需要额外引入okhttp-ws才能使用websocket的功能)

maven:

<dependency>  <groupId>com.squareup.okhttp3</groupId>  <artifactId>okhttp</artifactId>  <version>3.5.0</version></dependency><dependency>  <groupId>com.squareup.okhttp3</groupId>  <artifactId>mockwebserver</artifactId>  <version>3.5.0</version>  <scope>test</scope></dependency>

gradle:

compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile 'com.squareup.okhttp3:mockwebserver:3.5.0'

实现模拟服务端

MockWebServer mockWebServer = new MockWebServer();
mockWebServer.enqueue(new MockResponse().withWebSocketUpgrade(new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                System.out.println("server onOpen");
                System.out.println("server request header:" + response.request().headers());
                System.out.println("server response header:" + response.headers());
                System.out.println("server response:" + response);
            }
            @Override
            public void onMessage(WebSocket webSocket, String string) {
                System.out.println("server onMessage");
                System.out.println("message:" + string);
                //接受到5条信息后,关闭消息定时发送器
                if(msgCount == 5){
                    mTimer.cancel();
                    webSocket.close(1000, "close by server");
                    return;
                }
                webSocket.send("response-" + string);
            }
            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                System.out.println("server onClosing");
                System.out.println("code:" + code + " reason:" + reason);
            }
            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                System.out.println("server onClosed");
                System.out.println("code:" + code + " reason:" + reason);
            }
            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                //出现异常会进入此回调
                System.out.println("server onFailure");
                System.out.println("throwable:" + t);
                System.out.println("response:" + response);
            }
        }));

实现客户端

通过上面的MockWebServer的实例mockWebServer我们可以从中得到服务端的Host和Port:

String hostName = mockWebServer.getHostName();
int port = mockWebServer.getPort();
System.out.println("hostName:" + hostName);
System.out.println("port:" + port);

创建客户端:

String wsUrl = "ws://" + hostName + ":" + port + "/"
//新建client
        OkHttpClient client = new OkHttpClient.Builder()
                .build();
        //构造request对象
        Request request = new Request.Builder()
                .url(wsUrl)
                .build();
        //建立连接
        client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                mWebSocket = webSocket;
                System.out.println("client onOpen");
                System.out.println("client request header:" + response.request().headers());
                System.out.println("client response header:" + response.headers());
                System.out.println("client response:" + response);
                //开启消息定时发送
                startTask();
            }
            @Override
            public void onMessage(WebSocket webSocket, String text) {
                System.out.println("client onMessage");
                System.out.println("message:" + text);
            }
            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                System.out.println("client onClosing");
                System.out.println("code:" + code + " reason:" + reason);
            }
            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                System.out.println("client onClosed");
                System.out.println("code:" + code + " reason:" + reason);
            }
            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                //出现异常会进入此回调
                System.out.println("client onFailure");
                System.out.println("throwable:" + t);
                System.out.println("response:" + response); 
            }
        });

还需要一个消息定时发送器:

//每秒发送一条消息
    private static void startTask(){
        mTimer= new Timer();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                if(mWebSocket == null) return;
                msgCount++;
                boolean isSuccessed = mWebSocket.send("msg" + msgCount + "-" + System.currentTimeMillis());
                //除了文本内容外,还可以将如图像,声音,视频等内容转为ByteString发送
                //boolean send(ByteString bytes);
            }
        };
        mTimer.schedule(timerTask, 0, 1000);
    }

至此已经可以实现开头所要达到的效果。

运行结果

ws-result

对OkHttp Websocket的封装

俗话说得好,学以致用。为了进一步加深对okhttp websocket的理解与使用,对它做了一个封装,使得使用上更加清晰简洁,并且加入了断线重连的机制。

github:github.com/Rabtman/WsM…

里面同时包括了上面使用的例子,并且我会在下一篇文章进行okhttp websocket相关的源码阅读及分析,敬请期待。

最后欢迎大家指出我的不足并给予我一些建议。如果觉得文章所有帮助,那就请拿star砸向我的项目!那就请拿star砸向我的项目!那就请拿star砸向我的项目!(重要的事情说三遍)