最近因为需要使用socket,然后觉得原生java的socket,太过于繁琐了,而且偶尔会阻塞(也许是我菜把)。然后搜索过后,踩了几天的坑,最终解决了。忍不住打算做一下博文,因为网络上的文章,都是我出现了这个问题,然后,哇好巧呀,我也是。然后PASS。懵逼 = =,解决方法呢?所以有了这个博文的诞生。写的不好尽情见谅。
首先关于配置可以参考https://blog.csdn.net/dubismile/article/details/86580858。
然后进入正题吧。当我们使用netty作为服务端与底层设备进行通信的使用,除开特殊因素外,可能碰到的第一个坑就是在于转码问题。之前用原生Java写socket的时候没有遇到过这个问题,然后这次遇到,加上对于这一个也不算懂,只能努力找问题了。
当我们使用调试助手依照16进制发送80,他的10进制大于127,这时候,我们netty获取到的值,就会变成efbfbd,如果看到是乱码的请使用以下代码获取:
ByteBufUtil.hexDump(((String) msg).getBytes())
发现跟我们发送的80完全不多,那么是在什么环节除了问题呢?让我们使用调试,取出Object msg的值。惊了。居然变成这个不知道什么玩意了。起初的我一位是配置有问题,然后翻了一堆配置教程。。。然后没解决,后来想会不会是ChannelOption能设置读取出来的长度问题,然后再去了解和研究channelOption。再然后发现可能是byte的问题,那么就可能关于解码器和编码器的问题,因为Netty本身是内置了编码器和解码器的,然后我以为是我用的不对,就去了解编码器类型,然后替换尝试,都没有什么用。
于是乎,最后采取了自定义解码器了。先上代码了。
public class MyDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
//创建字节数组,buffer.readableBytes可读字节长度
byte[] b = new byte[buffer.readableBytes()];
//复制内容到字节数组b
buffer.readBytes(b);
//字节数组转字符串
String str = new String(b);
System.out.println(str);
out.add(bytesToHexString(b));
}
public String bytesToHexString(byte[] bArray) {
StringBuffer sb = new StringBuffer(bArray.length);
String sTemp;
for (int i = 0; i < bArray.length; i++) {
sTemp = Integer.toHexString(0xFF & bArray[i]);
if (sTemp.length() < 2)
sb.append(0);
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
public static String toHexString1(byte[] b) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < b.length; ++i) {
buffer.append(toHexString1(b[i]));
}
return buffer.toString();
}
public static String toHexString1(byte b) {
String s = Integer.toHexString(b & 0xFF);
if (s.length() == 1) {
return "0" + s;
} else {
return s;
}
}
}
修改ServerChannelInitializer.java
@Component
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
@Autowired
ServerChannelHandler serverChannelHandler;
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//IdleStateHandler心跳机制,如果超时触发Handle中userEventTrigger()方法
pipeline.addLast("idleStateHandler",
new IdleStateHandler(5, 0, 0, TimeUnit.MINUTES));
//字符串编解码器
// pipeline.addLast(
// new StringDecoder(),
// new StringEncoder()
// );
//修改了这里
pipeline.addLast("decoder", new MyDecoder());
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 4, -8, 0));
// pipeline.addLast("byteArrayEncoder", new ByteArrayEncoder());
//自定义Handler
pipeline.addLast("serverChannelHandler", serverChannelHandler);
}
}
至此,大工告成。
小结:在写的过程中,我在想为什么超过127后会变成负数,然后搜索了关于这块的资料,虽然大概知道怎么计算了,但是没啥用呀。果然在项目中,不断学习新的知识,填充自身很棒。这么一趟坑我就学到了很多。
老规矩写的不清晰的地方,可以指出,我会不定时更新和修改。一起加油
所有的伟大,都来自于一个勇敢的开始。