Netty接收16进制的坑

       最近因为需要使用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后会变成负数,然后搜索了关于这块的资料,虽然大概知道怎么计算了,但是没啥用呀。果然在项目中,不断学习新的知识,填充自身很棒。这么一趟坑我就学到了很多。

老规矩写的不清晰的地方,可以指出,我会不定时更新和修改。一起加油

所有的伟大,都来自于一个勇敢的开始。

在使用 Netty 发送 16 进制数据时,可以将数据转换成字节数组,然后使用 `ByteBuf` 对象进行封装,最后发送给对方。以下是一个简单的示例代码: ```java // 将 16 进制字符串转换成字节数组 String hexString = "2B 44 45 56 2F 31 2E 30 0D 0A"; hexString = hexString.replaceAll(" ", ""); byte[] data = new byte[hexString.length() / 2]; for (int i = 0; i < data.length; i++) { int index = i * 2; int j = Integer.parseInt(hexString.substring(index, index + 2), 16); data[i] = (byte) j; } // 使用 ByteBuf 对象进行封装 ByteBuf buf = Unpooled.buffer(data.length); buf.writeBytes(data); // 发送数据 Channel channel = ...; // 获取发送方的 Channel 对象 channel.writeAndFlush(buf); ``` 在这个示例代码中,我们首先将 16 进制字符串转换成字节数组,然后使用 `Unpooled.buffer` 方法创建一个 `ByteBuf` 对象,并将字节数组写入到 `ByteBuf` 对象中。最后,我们获取发送方的 `Channel` 对象,并通过该对象发送数据。 需要注意的是,在接收方收到数据时,也需要将接收到的字节数据转换成对应的 16 进制字符串。可以使用以下代码实现: ```java ByteBuf buf = ...; // 获取接收到的 ByteBuf 对象 byte[] receivedData = new byte[buf.readableBytes()]; buf.readBytes(receivedData); String hexString = ""; for (byte b : receivedData) { hexString += String.format("%02X ", b); } System.out.println("Received data: " + hexString); ``` 在这个示例代码中,我们首先读取接收到的 `ByteBuf` 对象,并将其转换成字节数组。然后,我们将字节数组转换成对应的 16 进制字符串,并打印出来。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值