老师安排的一个体检系统,其中需要使用身份证读卡器读取用户信息,并在前端展示相关信息,方便用户查询,进行下一步操作。
项目中使用了Netty构建RPC服务端,提供Socket和WebSocket连接和数据交互功能。身份证读卡器客户端是C++客户端开发,使用Socket建立与Netty服务端连接,并交互数据。
项目中遇到两个需要解决问题
问题一1.1 描述
C++客户端向Netty服务端发送数据,Netty服务器因为不知道数据包大小,会提前结束
- 真实传输数据:
{
"data" : {
"idCard" : "360123xxxx",
"name" : "xxx"
},
"key" : "00-50-56-C0-00-01",
"keyName" : "mac",
"module" : "examination",
"type" : "00"
}
- 实际接受数据:
通过查看处理代码:
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("接收到来自客户端的信息:{}", ctx.channel().remoteAddress().toString());
String requestData = (String)msg;
log.info("收到socket消息:"+ requestData);
Channel channel = ctx.channel();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
在调用channelRead0()函数,可能会出现还没有读取完数据,就提前调用channelReadComplete()函数进行停止读取,刷新操作。
1.3 解决方案:在ChannelPipeline中添加 LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)解码器,根据数据包前4个字节(unsignedInt)进行解析,获取数据包长度。根据已知长度获取数据。
问题二
2.1 描述
在根据上面的解决方式进行操作后,发现一直无法正常解析数据包,会提前结束。
2.2 原因分析:通过进行查看C++客户端传来的数据包,和通过Debug发现:
- 数据包
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 15 00 00 00 7b 0a 20 20 20 22 74 79 70 65 22 20 |....{. "type" |
|00000010| 3a 20 22 31 31 22 0a 7d 0a |: "11".}. |
+--------+-------------------------------------------------+----------------+
- Debug
可以发现,其实 LengthFieldBasedFrameDecoder()默认使用大端解析数据包,而实际传来数据是小端方式,因此会出现解析数据包长度长于实际数据包长度。
2.3 解决方案:
在 LengthFieldBasedFrameDecoder()上面指定使用小端解析就可以了
ctx.pipeline().addLast("length-decoder",new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN,Integer.MAX_VALUE, 0, 4, 0, 4,true));



