Android 一套完整的 Socket 解决方案
项目地址,喜欢点一个 star:
写在前面:
在上上周的时候,写了一篇文章:
在 Android 上,一个完整的 UDP 通信模块应该是怎样的?
文中介绍了在 Android 端,一个完整的 UDP 模块应该考虑哪些方面。当然了文中最后也提到了,UDP 的使用本身就有一些局限性,比如发送数据的大小有限制,属于不可靠协议,可能丢包。而且它是一对多发送的协议等等…如果能将这个模块能加入 TCP Socket 补充,那就比较完美解决了 Android 上端到端的通信。下面就来看看怎么去做。
整体步骤流程
先来说一下整体的步骤思路吧:
- 发送 UDP 广播,大家都知道 UDP 广播的特性是整个网段的设备都可以收到这个消息。
- 接收方收到了 UDP 的广播,将自己的 ip 地址,和双方约定的端口号,回复给 UDP 的发送方。
- 发送方拿到了对方的 ip 地址以及端口号,就可以发起 TCP 请求了,建立 TCP 连接。
- 保持一个 TCP 心跳,如果发现对方不在了,超时重复 1 步骤,重新建立联系。
整体的步骤就和上述的一样,下面用代码展开:
搭建 UDP 模块
public UDPSocket(Context context) {
this.mContext = context;
int cpuNumbers = Runtime.getRuntime().availableProcessors();
// 根据CPU数目初始化线程池
mThreadPool = Executors.newFixedThreadPool(cpuNumbers * Config.POOL_SIZE);
// 记录创建对象时的时间
lastReceiveTime = System.currentTimeMillis();
messageReceiveList = new ArrayList<>();
Log.d(TAG, "创建 UDP 对象");
// createUser();
}
首先进行一些初始化操作,准备线程池,记录对象初始的时间等等。
public void startUDPSocket() {
if (client != null) return;
try {
// 表明这个 Socket 在设置的端口上监听数据。
client = new DatagramSocket(CLIENT_PORT);
client.setReuseAddress(true);
if (receivePacket == null) {
// 创建接受数据的 packet
receivePacket = new DatagramPacket(receiveByte, BUFFER_LENGTH);
}
startSocketThread();
} catch (SocketException e) {
e.printStackTrace();
}
}
紧接着就创建了真正的一个 UDP Socket 端,DatagramSocket,注意这里传入的端口号 CLIENT_PORT 的意思是这个 DatagramSocket 在此端口号接收消息。
/**
* 开启发送数据的线程
*/
private void startSocketThread() {
clientThread = new Thread(