【摘要】 前言19年那会我还是用java去写的tcp,当然是另一个项目,也没有做沾包处理,今天重新把原来的项目给加上了粘包处理,当然还是选择用java语言.直接在原先的类上直接修改的.这是我用kotlin写的一个TCP粘包处理,思路也是同样的,只是写法不同,有兴趣可以去看下.Android Kotlin语言实现+TCP客户端开发+粘包处理class TcpService implements Runn…
前言
19年那会我还是用java去写的tcp,当然是另一个项目,也没有做沾包处理,今天重新把原来的项目给加上了粘包处理,当然还是选择用java语言.直接在原先的类上直接修改的.
这是我用kotlin写的一个TCP粘包处理,思路也是同样的,只是写法不同,有兴趣可以去看下.
Android Kotlin语言实现+TCP客户端开发+粘包处理
class TcpService implements Runnable
1
创建一个TCP连接类,该类实现Runnable,连接的过程中需要在子线程中去处理,所以我直接让该类实现接口.
public TcpService(OnListenerIndustrialObject objectCallBack) {
this.objectCallBack = objectCallBack;
isconnect = true;
// 放两个线程 一个发送的线程 一个读取接收消息的线程
executorService = Executors.newFixedThreadPool(2);
}
创建一个构造方法,初始化一些该类所需要的参数.我这方法里使用接口回调,回调一些当前的状态信息等,变量isconnect改变当前的是否可以连接TCP的状态 这里创建了一个只有两个线程的线程池.一个是发送消息的.一个是处理粘包的.
/**
* 设置ip地址
*/
public TcpService setIp(String ip) {
this.ip = ip;
return this;
}
public TcpService setProt(int prot) {
this.prot = prot;
return this;
}
开始之前需要传输对应的IP端口号,返回本类该对象.也可以链式调用.
@Override
public void run() {
readQueueData();
Log.i(TAG, “tcp run”);
while (isconnect) {
try {
socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(ip, prot);
Log.i(TAG, “” + ip + “,” + prot);
socket.connect(socketAddress, 30000);
if (socket.isConnected()) {
createIo();
}
//连接成功发送注册命令
sendCommand(“00030000020000000a01000000000000000000”);
//tcp收到命令之后返回来的数据
readTCPData();
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, “tcp connect exception”);
Log.i(TAG, “TCP reconnects in 5 seconds”);
objectCallBack.isNetWorkNormally(false);
closeTcp();
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Log.i(TAG, “tcp end”);
}
同样把这些写在循环当中,以防止因某些情况断开连接导致无法重新连接
readQueueData()这个方法就是处理粘包的问题,这个放在最后讲
private void createIo() throws Exception {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
}
1
2
3
4
连接成功之后创建SocketIO流,接收发送消息用
/**
* 发送命令
*
* @param registerCommand 命令
*/
synchronized void sendCommand(final String registerCommand) {
executorService.execute(new Runnable() {
@Override
public void run() {
try {
if (out != null) {
out.write(CodeUtil.hex2byte(registerCommand));
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
开启发送线程,这个命令权限公开出去,在外部可以直接调用
private void readTCPData() {
try {
byte[] bytes = new byte[1024];
int len = 0;
if (in != null) {
objectCallBack.isNetWorkNormally(true);
while ((len = in.read(bytes)) != -1) {
for (int i = 0; i < len; i++) {
queueData.offer(bytes[i]);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}