【安卓学习之socket】socket.io-client

【安卓学习之socket】socket.io-client

介绍

io.socket.client.Socket 是由 ‌Socket.IO‌ 团队开发的,其核心维护者为 ‌Automattic‌ 公司(即 WordPress 背后的公司)。

广泛用于 Android 应用中实现实时消息、聊天、通知等功能

地址

https://mvnrepository.com/artifact/io.socket/socket.io-client/versions
https://repo.maven.apache.org/maven2/io/socket/engine.io-client/
https://github.com/socketio/socket.io-client-java
https://gitee.com/hanmtou/socket.io-client-java

依赖

c 复制代码
    implementation 'io.socket:socket.io-client:2.1.2'

问题

想知道这个怎么将 JSONObject 发送出去

c 复制代码
	/**
	 * 初始化配置
	 */
    public void init() {
		this.mClient = new SocketClient.Builder().url(this.mUrl)
				.auth(UserId, Token)
				.socketMessageListener(this)
				.socketMapListen("auth", this.onAuthListener)
				.socketMapListen("index", this.onAuthListener)
				.socketMapListen("User", this.onUserListener)
				.socketMapListen("Notify", this.onNotifyListener)
				.socketMapListen("Message", this.onMessageListener)
				.socketMapListen("message", this.onRtcSdpMessageListener)
				.socketMapListen("quite", this.onQuiteListener).build();
    }
	/**
	 * 发送消息,暂不重载
	 */
    public void send() {
		JSONObject jSONObject = new JSONObject();
		jSONObject.put("replayId", Id);
		jSONObject.put("type", "candidate");
		jSONObject.put("label", sdpMLineIndex);// int
		jSONObject.put("id", sdpMid);// String
		jSONObject.put("candidate", sdp);// String
		this.mClient.emit(jSONObject);
    }
c 复制代码
public class SocketClient {
    private final Emitter.Listener mConnectListener,mErrorListener,mTimeOutListener;
    private final Emitter.Listener mReConnectListener,mRePingListener,mRePongListener;
    private Map<String, Emitter.Listener> mListenerMap;
    public SocketMessageListener mListener;
 
    public SocketClient(Builder builder) {
        if (!TextUtils.isEmpty(builder.url)) {
            try {
                IO.Options options = new IO.Options();
                options.forceNew = true;
                options.reconnection = true;
                options.reconnectionDelay = 10000;
                options.query = "uid=" + builder.uid + "&token=" + builder.token + "&device=1";
                mSocket = IO.socket(builder.url, options);
                mSocket .on(Socket.EVENT_CONNECT, mConnectListener);
                mSocket.on(Socket.EVENT_DISCONNECT, mDisConnectListener);
                mSocket.on(Socket.EVENT_CONNECT_ERROR, mErrorListener);
                mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, mTimeOutListener);
                mSocket.on(Socket.EVENT_RECONNECT, mReConnectListener);
                mSocket.on(Socket.EVENT_PING, mRePingListener);
                mSocket.on(Socket.EVENT_PONG, mRePongListener);
                mListenerMap = builder.listenerMap;
                if (mListenerMap!= null) {
                    for (Map.Entry next : mListenerMap.entrySet()) {
                        this.mSocket.on((String) next.getKey(), (Emitter.Listener) next.getValue());
                    }
                }
                mListener = builder.listener;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public void connect() {
        if (mSocket!= null) {
            mSocket.connect();
        }
    }

    public void disConnect() {
        if (mSocket!= null) {
            mSocket.close();
            mSocket.off();
        }
    }

     public void emit(JSONObject jSONObject) {
        mSocket.emit("Message", jSONObject);
    }
}

分析

io.socket.client.Socket.java

c 复制代码
/**
 * The socket class for Socket.IO Client.
 */
public class Socket extends Emitter {
    private int ids;
    private String nsp;
    private Manager io;
    
	/**
     * 触发一个事件。当你在最后一个参数中传递 {@link Ack} 时,则会执行确认回调。
     *
     * @param event 事件名称
     * @param args 要发送的数据(最后一个参数可能是应答事件)
     * @return 此对象的引用
     */
    @Override
    public Emitter emit(final String event, final Object... args) {
        if (RESERVED_EVENTS.containsKey(event)) {
            throw new RuntimeException("'" + event + "' is a reserved event name");
        }

        EventThread.exec(new Runnable() {
            @Override
            public void run() {
                Ack ack;
                Object[] _args;
                int lastIndex = args.length - 1;

                if (args.length > 0 && args[lastIndex] instanceof Ack) {
                    _args = new Object[lastIndex];
                    for (int i = 0; i < lastIndex; i++) {
                        _args[i] = args[i];
                    }
                    ack = (Ack) args[lastIndex];
                } else {
                    _args = args;
                    ack = null;
                }

                emit(event, _args, ack);
            }
        });
        return this;
    }

     /**
     * 触发一个带确认回调的事件
     *
     * @param event 事件名称
     * @param args 要发送的数据
     * @param ack 要调用的确认回调
     * @return 此对象的引用
     */
    public Emitter emit(final String event, final Object[] args, final Ack ack) {
        EventThread.exec(new Runnable() {
            @Override
            public void run() {
                JSONArray jsonArgs = new JSONArray();
                jsonArgs.put(event);

                if (args != null) {
                    for (Object arg : args) {
                        jsonArgs.put(arg);
                    }
                }
                // ===== 这边 type 是 EVENT 类型
                Packet<JSONArray> packet = new Packet<>(Parser.EVENT, jsonArgs);

                if (ack != null) {
                    logger.fine(String.format("emitting packet with ack id %d", ids));
                    Socket.this.acks.put(ids, ack);
                    packet.id = ids++;
                }

                if (Socket.this.connected) {
                    Socket.this.packet(packet);
                } else {
                    Socket.this.sendBuffer.add(packet);
                }
            }
        });
        return this;
    }
    
     /**
     * 发送
     */
    private void packet(Packet packet) {
        packet.nsp = this.nsp;
        this.io.packet(packet);
    }
}

io.socket.parser.Packet.java

c 复制代码
public class Packet<T> {

    public int type = -1;// ===== 这边 type 是 EVENT 类型
    public int id = -1;
    public String nsp;
    public T data;// ===== 这边 data 是 JSONArray 类型,第一个参数是"Message", 第二个参数是 JSONObject
    public int attachments;

    public Packet(int type, T data) {
        this.type = type;
        this.data = data;
    }
}

io.socket.client.Manager.java

c 复制代码
/**
 * Manager class represents a connection to a given Socket.IO server.
 */
public class Manager extends Emitter {
    private Parser.Encoder encoder;
    private Parser.Decoder decoder;

	public Manager(URI uri, Options opts) {
        this.opts = opts;
        this.nsps = new ConcurrentHashMap<>();
        this.subs = new LinkedList<>();
        this.timeout(opts.timeout);
        this.readyState = ReadyState.CLOSED;
        this.uri = uri;
        this.encoding = false;
        this.encoder = opts.encoder != null ? opts.encoder : new IOParser.Encoder();
        this.decoder = opts.decoder != null ? opts.decoder : new IOParser.Decoder();
    }
	void packet(Packet packet) {
 
        if (logger.isLoggable(Level.FINE)) {
            logger.fine(String.format("writing packet %s", packet));
        }
        final Manager self = this;

        if (!self.encoding) {
            self.encoding = true;
            this.encoder.encode(packet, new Parser.Encoder.Callback() {
                @Override
                public void call(Object[] encodedPackets) {
                    for (Object packet : encodedPackets) {
                        if (packet instanceof String) {
                            self.engine.write((String)packet);
                        } else if (packet instanceof byte[]) {
                            self.engine.write((byte[])packet);
                        }
                    }
                    self.encoding = false;
                    self.processPacketQueue();
                }
            });
        } else {
            self.packetBuffer.add(packet);
        }
    }
}

io.socket.parser.IOParser.java

c 复制代码
final public class IOParser implements Parser {
        @Override
        public void encode(Packet obj, Callback callback) {
        	// ===== 这边 type 是 EVENT 类型
        	// ===== 这边 data 是 JSONArray 类型,第一个参数是"Message", 第二个参数是 JSONObject
        	// HasBinary.hasBinary(obj.data) 的调用结果应该是false
            if ((obj.type == EVENT || obj.type == ACK) && HasBinary.hasBinary(obj.data)) {
                obj.type = obj.type == EVENT ? BINARY_EVENT : BINARY_ACK;
            }

            if (logger.isLoggable(Level.FINE)) {
                logger.fine(String.format("encoding packet %s", obj));
            }

            if (BINARY_EVENT == obj.type || BINARY_ACK == obj.type) {
                encodeAsBinary(obj, callback);
            } else {
                String encoding = encodeAsString(obj);// ===== 执行到这边 按照字符串处理
                callback.call(new String[] {encoding});
            }
        }

        private String encodeAsString(Packet obj) {
            StringBuilder str = new StringBuilder("" + obj.type);

            if (BINARY_EVENT == obj.type || BINARY_ACK == obj.type) {
                str.append(obj.attachments);
                str.append("-");
            }

            if (obj.nsp != null && obj.nsp.length() != 0 && !"/".equals(obj.nsp)) {
                str.append(obj.nsp);
                str.append(",");
            }

            if (obj.id >= 0) {
                str.append(obj.id);
            }

            if (obj.data != null) {
                str.append(obj.data);
            }

            if (logger.isLoggable(Level.FINE)) {
                logger.fine(String.format("encoded %s as %s", obj, str));
            }
            return str.toString();
        }
}

io.socket.hasbinary.HasBinary.java

c 复制代码
/**
 * 检测传入对象 obj.data 中是否包含二进制数据(如 Buffer、Blob、ArrayBuffer 等)。
 * 这个检测对于决定如何处理和编码数据包至关重要
 */
public class HasBinary {
	
    private static final Logger logger = Logger.getLogger(HasBinary.class.getName());
	
    private HasBinary() {}

    public static boolean hasBinary(Object data) {
        return _hasBinary(data);
    }

    private static boolean _hasBinary(Object obj) {
        if (obj == null) return false;

        if (obj instanceof byte[]) {
            return true;
        }

        if (obj instanceof JSONArray) {// == 第1次执行这个(JSONArray 中的 第一个参数是"Message")
            JSONArray _obj = (JSONArray)obj;
            int length = _obj.length();// 长度为2
            for (int i = 0; i < length; i++) {
                Object v;
                try {
                    v = _obj.isNull(i) ? null : _obj.get(i);
                } catch (JSONException e) {
                    logger.log(Level.WARNING, "An error occured while retrieving data from JSONArray", e);
                    return false;
                }
                if (_hasBinary(v)) {
                    return true;
                }
            }
        } else if (obj instanceof JSONObject) {// == 第2次执行这个(JSONArray 中的 第二个参数是 JSONObject)
            JSONObject _obj = (JSONObject)obj;
            Iterator keys = _obj.keys();
            while (keys.hasNext()) {
                String key = (String)keys.next();
                Object v;
                try {
                    v = _obj.get(key);
                } catch (JSONException e) {
                    logger.log(Level.WARNING, "An error occured while retrieving data from JSONObject", e);
                    return false;       
                }
                if (_hasBinary(v)) {
                    return true;
                }
            }
        }

        return false;
    }
}

█ 相关资料

提示:这里是参考的相关文章

  1. 2020-12-09 基于Socket.IO的Client封装-腾讯云开发者社区-腾讯云

█ 免责声明

博主分享的所有文章内容,部分参考网上教程,引用大神高论,部分亲身实践,记下笔录,内容可能存在诸多不实之处,还望海涵,本内容仅供学习研究使用,切勿用于商业用途,若您是部分内容的作者,不喜欢此内容被分享出来,可联系博主说明相关情况通知删除,感谢您的理解与支持!

转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/159728410

相关推荐
用户94261184462912 小时前
Android开发实战:ListView与RecyclerView使用详解
android
梦里花开知多少3 小时前
深入解析Launcher3 中的 CellLayout
android·面试
WangJunXiang63 小时前
MySQL高可用详细解析
android·数据库·mysql
我先去打把游戏先3 小时前
Git 一个本地仓库同时推送到两个远程仓库(私人 GitHub + 公司 Git)保姆级教程
git·vscode·单片机·嵌入式硬件·物联网·学习·github
悠哉悠哉愿意3 小时前
【物联网学习笔记】OLED
笔记·单片机·嵌入式硬件·物联网·学习
sensen_kiss3 小时前
CPT306 Principles of Computer Games Design 电脑游戏设计原理 Pt.5 VR 游戏
学习·游戏·vr
fengci.3 小时前
polar2026春季个人挑战赛(中等部分)
android
黑马源码库miui520863 小时前
JAVA国际版同城上门服务上门送水桶装水配送源码同城上门配送系统源码支持Android+IOS+H5
android·java·ios