日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Netty自定义协议

發布時間:2025/3/15 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Netty自定义协议 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、自定義協議要素

  • 魔數,用來在第一時間判定是否是無效數據包,如java的coffee baby
  • 版本號,可以支持協議的升級
  • 序列化算法,消息正文到底采用哪種序列化反序列化方式,可以由此擴展,例如:json、protobuf、hessian、jdk
  • 指令類型,是登錄、注冊、單聊、群聊… 跟業務相關
  • 請求序號,為了雙工通信,提供異步能力
  • 正文長度
  • 消息正文:如json,xml

二、代碼

  • 以下都是我們的自定義信息,我們希望對這些自定義信息類進行自定義編解碼操作,那么我們對他們的公共父類進行編解碼操作就可以。
  • 自定義編解碼器
  • @Slf4j public class MessageCodec extends ByteToMessageCodec<Message> {@Overridepublic void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {// 1. 4 字節的魔數out.writeBytes(new byte[]{1, 2, 3, 4});// 2. 1 字節的版本,out.writeByte(1);// 3. 1 字節的序列化方式 jdk 0 , json 1out.writeByte(0);// 4. 1 字節的指令類型out.writeByte(msg.getMessageType());// 5. 4 個字節out.writeInt(msg.getSequenceId());// 無意義,對齊填充out.writeByte(0xff);// 6. 獲取內容的字節數組ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(msg);byte[] bytes = bos.toByteArray();// 7. 長度out.writeInt(bytes.length);// 8. 寫入內容out.writeBytes(bytes);}@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {int magicNum = in.readInt();byte version = in.readByte();byte serializerType = in.readByte();byte messageType = in.readByte();int sequenceId = in.readInt();in.readByte();int length = in.readInt();byte[] bytes = new byte[length];in.readBytes(bytes, 0, length);ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));Message message = (Message) ois.readObject();log.debug("{}, {}, {}, {}, {}, {}", magicNum, version, serializerType, messageType, sequenceId, length);log.debug("{}", message);out.add(message);} }
  • 測試
  • public class TestMessageCodec {public static void main(String[] args) throws Exception {EmbeddedChannel channel = new EmbeddedChannel(new LoggingHandler(),new MessageCodec());LoginRequestMessage message=new LoginRequestMessage("zhangsan","123");channel.writeAndFlush(message);} }

    • 測試半包現象(不添加 LengthFieldBasedFrameDecoder)
    public class TestMessageCodec {public static void main(String[] args) throws Exception {EmbeddedChannel channel = new EmbeddedChannel(new LoggingHandler(),new MessageCodec());// encodeLoginRequestMessage message = new LoginRequestMessage("zhangsan", "123");// decodeByteBuf buf = ByteBufAllocator.DEFAULT.buffer();//手動調用encode方法用以測試decodenew MessageCodec().encode(null, message, buf);//切片1,用于證明LengthFieldBasedFrameDecoder解決了半包問題,因為直接發送buf是完整的包,無法看到半包現象ByteBuf s1 = buf.slice(0, 100);//切片2ByteBuf s2 = buf.slice(100, buf.readableBytes() - 100);s1.retain(); // 引用計數+1,不然由于s1,s2是零拷貝,物理上跟buf是同一塊內存, channel.writeInbound(s1)調用就會立即釋放,channel.writeInbound(s2)就調用不了channel.writeInbound(s1); // release 1//只發送s1,不發送s2//channel.writeInbound(s2);} }

    • 加上 LengthFieldBasedFrameDecoder再測試
    public class TestMessageCodec {public static void main(String[] args) throws Exception {EmbeddedChannel channel = new EmbeddedChannel(new LoggingHandler(),new LengthFieldBasedFrameDecoder(//楨最長長度、長度字段偏移量、長度字段占的字節,長度是否有調整,是否去除楨頭信息1024, 12, 4, 0, 0),// 在這里多添加一個LoggingHandler是為了證明,即使添加了LengthFieldBasedFrameDecoder,解決了粘包半包現象, // 但是,如果接收到的楨長度不對,也不會交給MessageCodec進行處理new LoggingHandler(),new MessageCodec());// encodeLoginRequestMessage message = new LoginRequestMessage("zhangsan", "123");// decodeByteBuf buf = ByteBufAllocator.DEFAULT.buffer();//手動調用encode方法用以測試decodenew MessageCodec().encode(null, message, buf);//切片1,用于證明LengthFieldBasedFrameDecoder解決了半包問題,因為直接發送buf是完整的包,無法看到半包現象ByteBuf s1 = buf.slice(0, 100);//切片2ByteBuf s2 = buf.slice(100, buf.readableBytes() - 100);s1.retain(); // 引用計數+1,不然由于s1,s2是零拷貝,物理上跟buf是同一塊內存, channel.writeInbound(s1)調用就會立即釋放,channel.writeInbound(s2)就調用不了channel.writeInbound(s1); // release 1//先只發送s1//channel.writeInbound(s2);} }

    • 發送s1,s2

    可以看到,信息完整接收

    參考視頻

    總結

    以上是生活随笔為你收集整理的Netty自定义协议的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。