Android 即时通信WebSocket和SocketIO的总结

本文总结了WebSocket和SocketIO在Android中的应用。WebSocket是一种基于TCP的全双工通信协议,简化了客户端与服务器的数据实时交换。而SocketIO是基于Node.js的JavaScript框架,支持WebSocket并提供丰富的API。文中还提供了Android集成WebSocket和SocketIO的示例代码,包括连接、发送消息和监听事件的操作。选择实时通信方案时,可根据服务器后台技术选WebSocket或SocketIO。

       WebSocket部分:

       首先应该先明确WebSocket是一个应用层协议,该协议是一种基于TCP连接上进行全双工通讯的协议(全双工通信允许发送数据和接收数据同时发生),因为有了WebSocket协议,使得客户端和服务器之间的数据实时交换变得更加简单,app客户端和服务器只需要完成一次握手(shake hand),两者之间就可以创建持久性的长连接,并进行双向数据传输。这个过程就像是A给B打个电话,电话通了之后就放在一边不挂掉,然后A有事了就直接拿起话筒找B了,不用拨号了直接就说,B有事了想找A也是同理。 WebSocket使用ws或者是wss的统一资源标识符,类似于HTTP和HTTPS,其中wss表示在TLS之上的WebSocket,如下所示,ws://121.40.165.18:8800就是合规范的url:

         https://blog.youkuaiyun.com/llew2011/article/details/53056165,这个博文的作者很详细的介绍了WebSocket协议,以及剖析了Android的开源WebSocket网络框架 autobahn-java,用这个开源库在自己的项目中可以快速搭建WebSocket实时通信的功能。

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

       

      SocketIO部分:

      许多语言、框架和服务器都提供了 WebSocket协议 的支持,SocketIO就是其中之一,它一个完全由JavaScript实现、基于Node.js、支持WebSocket协议用于实时通信、跨平台的开源框架。服务器那端的代码应该是JS,Node.js写的,这对于移动端来说并不重要,对于Android端来说集成如下库就可以了。

  implementation 'io.socket:socket.io-client:1.0.0'

        SocketIO这个框架封装的特别好,附上SocketIO的工具类,关键地方已经给出了明确的注释,如何设置,如何发起连接,如何发送消息,如何消息监听在如下的代码中都已俱备:

package com.xiaoluobei.facedetection.network.socket;


import android.os.Build;
import android.support.annotation.RequiresApi;

import com.xiaoluobei.facedetection.view.utils.STContext;

import org.json.JSONException;
import org.json.JSONObject;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

/**
 * Created by xjc on 2018/6/13.
 */

public class SocketIOClient {

    public Socket socket;

    private boolean isConnected = false;
    private Object lock = new Object();

    public static SocketIOClient mainEngine = null;


    public static SocketIOClient getInst() {
        if (mainEngine == null) {
            mainEngine = new SocketIOClient();
        }
        return mainEngine;
    }

    public SocketIOClient() {
        super();
        startExecutor();
    }

    public boolean send(JSONObject jsonObject) {
        boolean rtn = false;
        if (isConnected) {
            synchronized (lock) {
                //发送消息
                socket.emit("APP", jsonObject);
            }
        }

        return rtn;
    }



    public void startExecutor() {
        try {
            IO.Options op = new IO.Options();
            op.transports = new String[]{"websocket"};
            op.reconnection = true;
//	设置环节,IO.socket()里的内容是你服务器端的地址以及监听的端口
            socket = IO.socket(STContext.getInst().SOCKETURL, op);
//	监听到Socket.EVENT_CONNECT这个定义好的命令,则说明连接客户端和服务器
            socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    isConnected = true;
                    System.out.println("socketConnect");
 //按照业务逻辑发送数据
                    socket.emit("CT", "CDD");
                    sendL01();
                }

            }).on("CC", new Emitter.Listener() {   //和服务器定义好的CC命令,监听
                @RequiresApi(api = Build.VERSION_CODES.N)
                @Override
                public void call(Object... args) {

                    ProtocolProcessing.getInst().protocol(args[0].toString());

                }
            }).on(Socket.EVENT_RECONNECT, new Emitter.Listener() {


                @Override
                public void call(Object... args) {
                    //JSONObject obj = (JSONObject)args[0];
                    System.out.println("EVENT_RECONNECT");
                }

            }).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {   //监听Socket连接是中断。

                @Override
                public void call(Object... args) {
                    //JSONObject obj = (JSONObject)args[0];
                    System.out.println("EVENT_CONNECT_ERROR");
                }

            }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {

                @Override
                public void call(Object... args) {
                    System.out.println("EVENT_DISCONNECT");
                }
            });
               //连接    
            socket.connect();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendL01(){

        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("protocol","L01");
            jsonObject.put("cid" ,STContext.getInst().pcNumber);
            send(jsonObject);
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }


}

       在界面活动中,直接单例模式new就行了

        //Socket
        if (SocketIOClient.mainEngine == null)
        {
            SocketIOClient.getInst();
        } else
        {
            SocketIOClient.getInst().startExecutor();
        }

   

      在上述的工具类代码中,只写了一种发送消息的emit方式,其实发送的常见写法主要有以下3种:

socket.emit('action');   //表示发送了一个action命令,命令是字符串的,在另一端接收时,可以这么写: 

       socket.on('action',function(){...});
        

socket.emit('action',data);    //表示发送了一个action命令,还有data数据,在另一端接收时,可以这么写:

       socket.on('action',function(data){...});
        
socket.emit(action,arg1,arg2);   //表示发送了一个action命令,还有两个数据,在另一端接收时,可以这么写: 

       socket.on('action',function(arg1,arg2){...});

 ========================= =======================================================================

         

          上面的代码是关于使用框架的层面上,下面看具体的源码,在Manager这个类中:

 /**
     * Initializes {@link Socket} instances for each namespaces.
     *
     * @param nsp namespace.
     * @param opts options.
     * @return a socket instance for the namespace.
     */
    public Socket socket(final String nsp, Options opts) {
        Socket socket = this.nsps.get(nsp);
        if (socket == null) {
            socket = new Socket(this, nsp, opts);
            Socket _socket = this.nsps.putIfAbsent(nsp, socket);
            if (_socket != null) {
                socket = _socket;
            } else {
                final Manager self = this;
                final Socket s = socket;
                socket.on(Socket.EVENT_CONNECTING, new Listener() {
                    @Override
                    public void call(Object... args) {
                        self.connecting.add(s);
                    }
                });
                socket.on(Socket.EVENT_CONNECT, new Listener() {
                    @Override
                    public void call(Object... objects) {
                        s.id = self.generateId(nsp);
                    }
                });
            }
        }
        return socket;
    }

        如上可知,在底层源码中,当监听到Socket.EVENT_CONNECT这个连接成功的消息时候,底层对socketId进行了赋值,id就像每个客户端的身份证一样,socketId 是 socket.io 随机生成的,保证不重复,客户端就是根据这个socketId,给每个客户端精准的发送消息。

        如上便是WebSocket和SocketIO的总结全部,如果服务器后台用WebSocket的,那移动端就选前者,如果后台用SocketIO, 那移动端app就选后者,如果公司自己搭建的长连接不稳定总掉,那么就考虑使用三方推送,根据具体情况具体选用哪种。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值