说起okhttp,想必各位老司机们一定都不会陌生,但是okhttp还可以进行websocket通信你造吗?下面就让我们一起来深入浅出okhttp websocket吧!
OkHttp Websocket
首先我们先明确一下要实现的效果:
- 客户端与服务端建连
- 客户端向服务端发送消息
- 服务端在接受消息后以“response-接受的消息内容“的形式返回给客户端
- 当服务端收到第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);
}
至此已经可以实现开头所要达到的效果。
运行结果
对OkHttp Websocket的封装
俗话说得好,学以致用。为了进一步加深对okhttp websocket的理解与使用,对它做了一个封装,使得使用上更加清晰简洁,并且加入了断线重连的机制。
github:github.com/Rabtman/WsM…
里面同时包括了上面使用的例子,并且我会在下一篇文章进行okhttp websocket相关的源码阅读及分析,敬请期待。
最后欢迎大家指出我的不足并给予我一些建议。如果觉得文章所有帮助,那就请拿star砸向我的项目!那就请拿star砸向我的项目!那就请拿star砸向我的项目!(重要的事情说三遍)