WebSocketClient

房学文
2023-12-01
package com.example.ewdatasystem_android.websocket;

import com.example.util.LogUtil;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 2020/1/6 10:29
 *
 * @description
 *转载的,忘记原链接了。。。。
 *
 */
public class MyWSClient extends WebSocketClient {

    private static MyWSClient instance;
    private static URI sUri;
    private long mWsXinTiao;
    private Timer mTimer;

    /**
     * 之所以要用单例模式,是因为需要重连导致存在多线程并发的问题,会导致同时接收到多条相同信息,所以只能有一个实例。
     * 不使用的话可能报错(WebSocketClient objects are not reuseable)
     * <p>
     * 根据https://blog.csdn.net/hizhangyuping/article/details/81779364
     *
     * @return
     */
    public static MyWSClient getInstance() {
        if (instance == null) {
            synchronized (MyWSClient.class) {
                if (instance == null) {
                    instance = new MyWSClient(sUri);
                }
            }
        }
        return instance;
    }

    public MyWSClient(URI serverUri) {
        super(serverUri);
    }

    /**
     * step 1:
     * 需要先调用,设置服务端的 url
     */
    public static void setUri(String url) {
        try {
            sUri = new URI(url);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    /**
     * step 2:连接 websocket
     */
    public void onConnect() {
        //设置10秒后开始ping
        setConnectionLostTimeout(1000);
        //开始连接
        connect();
    }

    /**
     * 连接成功
     *
     * @param handshakedata
     */
    @Override
    public void onOpen(ServerHandshake handshakedata) {
        LogUtil.e("连接成功");
        clientLisenter.onOpen(handshakedata);
    }

    /**
     * 接收到的消息
     *
     * @param message
     */
    @Override
    public void onMessage(String message) {
        LogUtil.e("接收到的消息:" + message);
        clientLisenter.onMessage(message);
//        EventBus.getDefault().post(new SocketMessage(message));
    }


    /**
     * 断开连接
     *
     * @param code
     * @param reason
     * @param remote true 主机断开 false 客户端主动断开
     */
    @Override
    public void onClose(int code, String reason, boolean remote) {
        clientLisenter.onClose(code, reason, remote);
        if (remote) {
            onReconnect();
        }
    }

    /**
     * 连接出错
     *
     * @param ex
     */
    @Override
    public void onError(Exception ex) {
        if (ex != null) {
            clientLisenter.onError(ex);
        }
        onReconnect();
    }

    /**
     * ping通时的方法
     * <p>
     * 此方法可以判断websocket是否连接,如果超过超就重新连接
     * <p>
     * 我使用的是EventBus通信 通信比较方便
     *
     * @param conn
     * @param f
     */
    @Override
    public void onWebsocketPong(WebSocket conn, Framedata f) {
        super.onWebsocketPong(conn, f);
        clientLisenter.onWebsocketPong(conn, f);
        mWsXinTiao = System.currentTimeMillis();
        mTimer = new Timer();
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (System.currentTimeMillis() - mWsXinTiao > 30 * 1000) {
                    //接收不到ping时重新连接
                    onReconnect();
                }
            }
        }, 2000, 35 * 1000);//比心跳时间多一点 也没事。
//        EventBus.getDefault().post(new SocketMessage("ping"));
    }

    /**
     * 重新连接方法
     * <p>
     * 先关闭连接再使用reconnect()方法
     * <p>
     * reconnect()方法要放在子线程里否则会报错
     * <p>
     * You cannot initialize a reconnect out of the websocket thread. Use reconnect in another thread to insure a successful cleanup.
     * (无法从WebSocket线程初始化重新连接。在另一个线程中使用Reconnect以确保成功清理。)
     */
    public void onReconnect() {
        onCloseWebsocket();
        clientLisenter.onReconnect();
        if (!isOpen()) {
            Runnable sendable = new Runnable() {
                @Override
                public void run() {
                    LogUtil.e("websocket reconnect");
                    reconnect();
                }
            };
            new Thread(sendable).start();
        }

    }

    /**
     * 发送信息
     *
     * @param msg
     */
    public void sendMsg(String msg) {
        if (isOpen()) this.send(msg);
        LogUtil.e("ws- 发送  message:" + msg);
    }

    /**
     * 关闭websocket连接
     */
    public void onCloseWebsocket() {
        try {
            this.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private ClientLisenter clientLisenter;

    public interface ClientLisenter {
        void onOpen(ServerHandshake handshakedata);

        void onMessage(String message);

        void onClose(int code, String reason, boolean remote);

        void onError(Exception ex);

        void onWebsocketPong(WebSocket conn, Framedata f);

        void onReconnect();
    }

    public void setClientLisenter(ClientLisenter clientLisenter) {
        this.clientLisenter = clientLisenter;
    }

    //使用
    private void method(){
//        try {
//            //设置连接地址 WEB_SOCKET_HOST时你的websocket地址
//            MyWSClient.setUri(returnUrl("18824403202","12345"));
//            //开始连接
//            MyWSClient.getInstance().onConnect();
//            MyWSClient.getInstance().setClientLisenter(new MyWSClient.ClientLisenter() {
//                @Override
//                public void onOpen(ServerHandshake handshakedata) {
//                    LogUtil.e("onOpen");
//                }
//
//                @Override
//                public void onMessage(String message) {
//                    LogUtil.e("onMessage:"+message);
//                }
//
//                @Override
//                public void onClose(int code, String reason, boolean remote) {
//                    LogUtil.e(remote ? "服务器Cut" : "客户端Cut");
//                }
//
//                @Override
//                public void onError(Exception ex) {
//                    LogUtil.e(String.format("websocket 出现错误,错误原因:%s\n", ex.getMessage()));
//                }
//
//                @Override
//                public void onWebsocketPong(WebSocket conn, Framedata f) {
//                    LogUtil.e("onWebsocketPong");
//                }
//
//                @Override
//                public void onReconnect() {
//                    LogUtil.e("onReconnect");
//                }
//            });
//        } catch (Exception e) {
//            LogUtil.e("错误" + e.getMessage());
//            MyWSClient.getInstance().onReconnect();
//        }
    }
}
 类似资料:

相关阅读

相关文章

相关问答