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就选后者,如果公司自己搭建的长连接不稳定总掉,那么就考虑使用三方推送,根据具体情况具体选用哪种。
本文总结了WebSocket和SocketIO在Android中的应用。WebSocket是一种基于TCP的全双工通信协议,简化了客户端与服务器的数据实时交换。而SocketIO是基于Node.js的JavaScript框架,支持WebSocket并提供丰富的API。文中还提供了Android集成WebSocket和SocketIO的示例代码,包括连接、发送消息和监听事件的操作。选择实时通信方案时,可根据服务器后台技术选WebSocket或SocketIO。
5816

被折叠的 条评论
为什么被折叠?



