Java网络编程基础知识:大小端原理(java默认采用大端、补码存储),网络粘包、半包解决方案,netty实现百万数据传输

一、大小端原理(java默认采用大端、补码存储)

 #java大小端原理:大端(高位字节存储在低地址,低位字节存储在高地址),小端(高位字节储存在高地址,低位字节存储在低地址)
 public static void main(String[] args) {
        //java大小端原理:大端(高位字节存储在低地址,低位字节存储在高地址),小端(高位字节储存在高地址,低位字节存储在低地址)
        ByteBuf buf = Unpooled.buffer(2);
        //大端模式写入
        buf.writeInt(1254);
        //大端模式写入
        buf.writeIntLE(1254);
        System.out.println( "字节数组:" + Arrays.toString(buf.array()));

        //大端字节
        byte[] bigByte = {0, 0, 4, -26};
        //小端字节
        byte[] smallByte = {-26, 4, 0,0};

        //10001 1010 = -26
        System.out.println( "-26 = " + Integer.toBinaryString(-26));
        System.out.println( "-26 二进制补码:" + "11111111111111111111111111100110");
        System.out.println( "-26 二进制反码:" + "11111111111111111111111111100101");
        System.out.println( "-26 二进制原码:" + "10000000000000000000000000011010");
        //00000 0100 = 4
        System.out.println( "4 = " + Integer.toBinaryString(4));
        System.out.println( "4 二进制补码:" + "00000000000000000000000000000100");
        System.out.println( "4 二进制反码:" + "00000000000000000000000000000100");
        System.out.println( "4 二进制原码:" + "00000000000000000000000000000100");

        //大端解码
        int big = (((bigByte[0]) << 24 & 0xFF000000)

                | ((bigByte[0+1]<<16) & 0xFF0000)

                | ((bigByte[0+2]<<8)& 0xFF00)

                | ((bigByte[0+3]) & 0xFF));
        System.out.println("大端解码:" + big);

        //小端解码
        int small = ((smallByte[0] & 0xFF)

                | ((smallByte[0+1]<<8) & 0xFF00)

                | ((smallByte[0+2]<<16)& 0xFF0000)

                | ((smallByte[0+3]<<24) & 0xFF000000));
        System.out.println("小端解码:" + small);

        System.out.print( "补码方式定义小端-解码:");
        System.out.println(
                ((0b11111111111111111111111111100110) & 0xff |
                        ((4) << 8) & 0xff00 |
                        ((0) << 16) & 0xff0000) |
                        ((0) << 24) & 0xff000000);

        //小端解码 -8587
        byte[] e = {(byte) 0x75,(byte) 0xde};
        System.out.println("crc16-小端解码:" + (short)(((e[1] << 8) & 0xff00) | e[0] & 0xff));
    }
	
	/*
     ***************控制台打印运行结果***************
     字节数组:[0, 0, 4, -26, -26, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
     -26 = 11111111111111111111111111100110
     -26 二进制补码:11111111111111111111111111100110
     -26 二进制反码:11111111111111111111111111100101
     -26 二进制原码:10000000000000000000000000011010
     4 = 100
     4 二进制补码:11111111111111111111111111100110
     4 二进制反码:11111111111111111111111111100101
     4 二进制原码:10000000000000000000000000011010
     大端解码:1254
     小端解码:1254
     补码方式定义小端-解码:1254
     或运算原理(小端解码):1254
     crc16-小端解码:-8587
     */

或运算及解码原理
在这里插入图片描述

二、网络传输中粘包、半包处理

粘包半包

	//自定义解码方法
	int length, head;
    while (true) {
        byteBuf.markReaderIndex();
        head = byteBuf.readIntLE();
        length = byteBuf.readIntLE();
        if (length >= 18&& head == 0xAABBCCDD) {
            logger.debug("head:{},length:{}", head, length);
            break;
        }
        byteBuf.resetReaderIndex();
        byte temp = byteBuf.readByte();
        logger.debug("skip a byte:{},channelId:{}", temp, channelHandlerContext.channel().id().asShortText());
        if (byteBuf.readableBytes() < BASE_LENGTH) {
            return;
        }
    }
//desc:使用netty解码器解解决网络粘包问题
//param1: 指定小端解码 (ByteOrder.LITTLE_ENDIAN)
//param2: 单个包最大长度 (Integer.MAX_VALUE,)
//param3: 长度字段开始位置偏移量 (4)
//param4: 长度字段所占字节数 (4)
//param5: 长度字段默认表示后续报文的长度 (-8)
//param6: 从解码帧中剥离的第一个字节数(0表示解码过程中不丢弃任何数据)(0)
//param7: 默认为true,表示读取到长度域的值超过Integer.MAX_VALUE时抛异常,false表示真正读取完才抛异常,建议不要修改,否则可能会造成内存溢出 (true)
LengthFieldBasedFrameDecoderlengthFieldBasedFrameDecoder =
                            new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN,Integer.MAX_VALUE, 4, 4, -8, 0,true);
/**
 *@Desc:自定义IEC04协议粘包处理
 */
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
       // 记录包头开始的index  
       int beginReader;  
       int newDataLength = 0;
       while (true) {  
           // 获取包头开始的index  
           beginReader = buffer.readerIndex();  
           // 记录一个标志用于重置
           buffer.markReaderIndex();  
           // 读到了协议的开始标志,结束while循环  
           if (buffer.readByte() == Iec104Constant.HEAD_DATA) {
           	// 标记当前包为新包
           	//读取包长度
           	byte newDataLengthByte = buffer.readByte();
               newDataLength = newDataLengthByte & 0xFF;
               break;
           }
           continue;
       }

       if (buffer.readableBytes() < newDataLength) {
           buffer.readerIndex(beginReader);
           return;
       }

       newDataLength = newDataLength +  2;
       //恢复指针
       buffer.readerIndex(beginReader);
       ByteBuf data = buffer.readBytes(newDataLength);
       out.add(data); 
}

私有报文协议

报文格式
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值