当前位置: 首页>后端>正文

前端微信小程序与java后端 socket 模拟心跳机制 java实现 android websocket 心跳

1、快速使用

项目中的使用,以github的开源库org.java-websocket:Java-WebSocket:1.3.8为例,并且封装了工具类,快速上手。
1、org.java-websocket:Java-WebSocket的github地址:https://github.com/TooTallNate/Java-WebSocket
2、我封装的工具类WebSocketUtils.java的代码(下面有使用和讲解),思想是这样的:

一、重连机制。代码中有备注,在close()中重连。
二、心跳机制。工具类中,我是通过Observable.interval定时执行,10秒钟一次心跳。
三、后台返回的消息和给后台发送消息。在onMessage()中返回,和后台约定需要的数据,发送数据是通过sendMessage(),也是和后台约定好数据格式就好。

public class WebSocketUtils {
    private String TAG = "web_socket";
    private static WebSocketUtils instance = null;
    WebSocketClient client;
    //转成的要操作的数据
    URI uri;
    //后台连接的url
    String address = "ws://114.55.103.198:8989/";
    //连接是否关闭,用于判断是主动关闭还是断开,断开需要重连
    boolean isHandClose;
    //记录心跳重联的次数
    int reconnectTimes;
    //心跳timer
    Disposable timerHeart;
    //重连timer
    Disposable timer;

    //懒加载单例模式,synchronized确保线程安全。
    // 适合没有多线程频繁调用的情况,多线程频繁调用的时候,可以用双重检查锁定DCL、静态内部类、枚举 等方法,文章后面会详细介绍。
    public static synchronized WebSocketUtils getInstance() {
        if (instance == null) {
            instance = new WebSocketUtils();
        }
        return instance;
    }

    public void initSocket() {
        if (null != client && client.isOpen()) {
            EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CONNECT_SUCCESS, "登录成功!", ""));
            return;
        }
        isHandClose = false;
        startSocket();
    }

    public void startSocket() {
        try {
            uri = new URI(address);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        if (null == client || !client.isOpen()) {
            client = new WebSocketClient(uri) {
                @Override
                public void onOpen(ServerHandshake serverHandshake) {
                    reconnectTimes = 0;
                    if (timer != null) {
                        timer.dispose();
                    }
                    //socket连接成功,通过eventbus通知房间,用户可以加入房间了
                    EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CONNECT_SUCCESS, "连接成功!", ""));
                    LogUtils.eTag(TAG, "连接成功");
                    registerWebSocket();
//10秒钟进行一次心跳,防止异常断开
                    timerHeart = Observable.interval(10, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("type", "ping");
                            sendMessage(jsonObject.toString());
                        }
                    });
                }

                @Override
                public void onMessage(String s) {
                //后台返回的消息
                    EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_RECEIVE_SUCCESS, "收到消息!", s));
                    LogUtils.eTag(TAG, "收到消息", s);
                }

                @Override
                public void onClose(int i, String s, boolean b) {
                    if (isHandClose) {
                        EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CONNECT_SUCCESS_BY_HAND, "主动关闭成功!", s));
                        LogUtils.eTag(TAG, "主动关闭成功", s);
                        reconnectTimes = 0;
                        if (timer != null) {
                            timer.dispose();
                        }
                        if (timerHeart != null) {
                            timerHeart.dispose();
                        }
                    } else {
                        //非正常关闭进行重连,重连每次两秒,最多十次
                        timer = Observable.timer(2, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
                            @Override
                            public void accept(Long aLong) throws Exception {
                                LogUtils.eTag(TAG, "重连");
                                reconnectTimes = reconnectTimes + 1;
                                startSocket();
                            }
                        });
                        //重联超过十次没成功,结束重连
                        if (reconnectTimes > 10) {
                            EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CLOSE_SUCCESS, "关闭成功!", s));
                            LogUtils.eTag(TAG, "关闭成功", s);
                            reconnectTimes = 0;
                            if (timer != null) {
                                timer.dispose();
                            }
                            if (timerHeart != null) {
                                timerHeart.dispose();
                            }
                        }
                    }
                }

                @Override
                public void onError(Exception e) {
                    EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_ERROR, "出现错误!", ""));
                    LogUtils.eTag(TAG, "出现错误", e.getMessage());
                }
            };
            client.connect();
        }
    }

    //向服务器发送消息
    public void sendMessage(String s) {
        if (client == null || client.isConnecting() || client.isClosed() || !client.isOpen()) {
            LogUtils.eTag(TAG, "未建立实时通信");
            return;
        }
        try {
            client.send(s);
            LogUtils.eTag(TAG, "发送消息:", s);
        } catch (Exception e) {
            e.printStackTrace();
            startSocket();
        }
    }

    //关闭socket
    public void closeSocket() {
        isHandClose = true;
        if (client != null) {
            client.close();
            client = null;
        }
    }

    //向服务器发送初始化信息
    void registerWebSocket() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", "init");
        jsonObject.put("token", MyApplication.getInstance().getToken());
        sendMessage(jsonObject.toString());
    }

    //和服务器约定的传递的参数
    public void sendData(String type, String room_id) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", type);
        jsonObject.put("token", MyApplication.getInstance().getToken());
        jsonObject.put("room_id", room_id);
        sendMessage(jsonObject.toString());
    }

}

3、工具类的使用:
一、在需要用的地方初始化 , WebSocketUtils.getInstance().initSocket()
二、需要传递给后台的数据,举例: WebSocketUtils.getInstance().sendData(“setRoomManager”, id, user_id)。sendData()函数的参数根据情况自己配置,和后台约定好就行。
三、结束使用websocket的时候调用, WebSocketUtils.getInstance().closeSocket()

详细讲解:

把这篇文章放到语音直播间分类,是因为语音直播间刚刚用到,而且端对端的实时通信用websocket节省带宽和性能。Android与服务器的通信方式主要是两种:一是Http通信,一是Socket通信。两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求。


https://www.xamrdz.com/backend/33x1962928.html

相关文章: