Open marclee44 opened 2 years ago
之前写过一篇MQTT客户端初体验——eclipse/paho.mqtt.android,这次正好需要,类似的写一篇WebSocket的。
简介
HTTP协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理,HTTP协议无法实现服务器主动向客户端发起消息。 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步JavaScript和 XML(AJAX)请求实现长轮询。轮询的效率低,非常浪费资源。 Websocket应运而生,WebSocket连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。
特点
okhttp3.WebSocket
okhttp应该算是Android中使⽤最⼴泛的⽹络库了,我们通常会利⽤它来实现HTTP请求,实际上它还可以⽀持WebSocket,并且使⽤起来也⾮常的便捷。这里我们尝试写一个带自动重连功能的客户端。
okhttp
build.gradle
implementation "com.squareup.okhttp3:okhttp:4.9.3"
AndroidManifest.xml
<service android:name=".WebSocketService" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="com.space365.receiver.intent.action.ReceiveWebSocket"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>
创建WebSocketListener(事件监听)
private class WebSocketClient extends WebSocketListener { @Override public void onOpen(@NonNull WebSocket webSocket, @NonNull Response response) { super.onOpen(webSocket, response); online = true; Logger.i("WebSocket connect succeed!"); } @Override public void onClosed(@NonNull WebSocket webSocket, int code, @NonNull String reason) { online = false; //非正常退出code,则重连 if (code != CLOSE_CODE) { Logger.e("WebSocket closed! Reason: %s", reason); reConnect(); } } @Override public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, @Nullable Response response) { Logger.e(t, "WebSocket closed with error!"); online = false; reConnect(); } @Override public void onMessage(@NonNull WebSocket webSocket, @NonNull String text) { Logger.i(text); } }
创建WebSocket客户端
public class WebSocketService extends Service { private static final int CLOSE_CODE = 1000; private static final String CLOSE_REASON = "destroy"; private String host; private WebSocket webSocket; private boolean online; @Nullable @Override public IBinder onBind(Intent intent) { return new MyBinder(); } @Override public void onCreate() { Logger.i("WebSocketService onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Logger.i("WebSocketService onStartCommand"); host = "ws://ip:port/channel/xxxx-changed"; connect(); return START_NOT_STICKY; } private void connect() { OkHttpClient client = new OkHttpClient.Builder() .build(); Request request = new Request.Builder() .url(host) .build(); webSocket = client.newWebSocket(request, new WebSocketClient()); } //RxJava,3秒延迟后重新连接 private void reConnect() { disposables.add( Single.timer(3, TimeUnit.SECONDS) .subscribe(p -> connect()) ); } private final CompositeDisposable disposables; { disposables = new CompositeDisposable(); } private class MyBinder extends Binder { WebSocketService getService() { return WebSocketService.this; } } private class WebSocketClient extends WebSocketListener { ... } }
private void publish(String message) { if (online) { if (webSocket.send(message)) { Logger.i("WebSocket publish succeed!"); } else { Logger.e("WebSocket publish failed!"); } } else { Logger.e("WebSocket is not connected, publish failed!"); } }
退出时断开连接
private static final String CLOSE_REASON = "destroy"; @Override public void onDestroy() { Logger.i("WebSocketService onDestroy"); if (online) { webSocket.close(CLOSE_CODE, CLOSE_REASON); } webSocket.cancel(); disposables.dispose(); super.onDestroy(); }
之前写过一篇MQTT客户端初体验——eclipse/paho.mqtt.android,这次正好需要,类似的写一篇WebSocket的。
HTTP协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理,HTTP协议无法实现服务器主动向客户端发起消息。 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步JavaScript和 XML(AJAX)请求实现长轮询。轮询的效率低,非常浪费资源。 Websocket应运而生,WebSocket连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。
okhttp
应该算是Android中使⽤最⼴泛的⽹络库了,我们通常会利⽤它来实现HTTP请求,实际上它还可以⽀持WebSocket,并且使⽤起来也⾮常的便捷。这里我们尝试写一个带自动重连功能的客户端。build.gradle
中,仅需添加okhttp
的引用。这里我们使用4.9.3版本AndroidManifest.xml
中,需要声明服务,以便App在后台时也能保持WebSocket连接创建WebSocketListener(事件监听)
创建WebSocket客户端
退出时断开连接