公司服务于农业物联网行业,由我负责开发与.net代理服务(代理控制器)的通信,根据前期的建设情况,选择Socket自由协议通信,报文投标首字节68H、2字节长度、68H,末尾1字节校验位+16H。
我用Vertx创建TCP client监听代理服务,实现通信。处理器接收buffer,我需要对buffer进行解包,由于是自由协议,无法自动实现粘包、拆包的处理,于是自己写了部分代码,也就是本文的重点。
/**
* description: BufferWrapper <br>
* date: 2020/6/9 8:50 <br>
* author: jiasp <br>
* version: 1.0 <br>
*/
public class BufferWrapper {
private Buffer buffer;
private Buffer netxtBuffer;
private Buffer tempBuffer;
public boolean hasNextBuffer(){
if(buffer == null)return false;
if(buffer.length()>=(buffer.getUnsignedShort(1)+6)){
return true;
}else {
//记录
tempBuffer = buffer;
return false;
}
}
public Buffer nextBuffer(){
int len = buffer.getUnsignedShort(1);
//System.out.println("nextBuffer:len is "+len);
if(buffer.length()>(len+6)){
netxtBuffer = buffer.getBuffer(0, buffer.getUnsignedShort(1) + 6);
//System.out.println("OrginBuffer is "+ByteUtils.byteToHex(buffer.getBytes()));
buffer = buffer.getBuffer(buffer.getUnsignedShort(1) + 6,buffer.length());
//System.out.println("RemainBuffer is "+ByteUtils.byteToHex(buffer.getBytes()));
return netxtBuffer;
}else if(buffer.length()==(len+6)){
netxtBuffer = buffer;
buffer = null;
return netxtBuffer;
}else if(buffer.length()<(len+6)){
netxtBuffer = null;
System.out.println("this is halfBuffer that"+ByteUtils.byteToHex(buffer.getBytes()));
return netxtBuffer;
}
return netxtBuffer;
}
public Buffer getHalfBuffer(){
return tempBuffer;
}
public BufferWrapper(Buffer buffer){
this.buffer = buffer;
}
public BufferWrapper(Buffer buffer,Buffer halfBuffer){
this.buffer = halfBuffer.appendBuffer(buffer);
}
}
主要实现了一个buffer的包装类,然后接收buffer之后创建一个BufferWrapper对象,然后处理粘包和拆包,剩下的半包需要在调用类中用对象缓存,便于下一次的buffer进行append操作。
实际效果还可以,但是考虑到EventLoop线程是异步非阻塞的,假如待解包较多仍然会导致线程阻塞(默认2秒),因此,建议此部分最好是先接消息队列或者Redis(订阅模式),防止EventLoop线程阻塞,最后慢慢解析。我这边数据量不大暂时就是同步处理的,笔记本8个线程的话,几千个并发还能应付,后期考虑将代码异步化处理。
未完待续....