├── .gitignore ├── LICENSE ├── README.md ├── netty-in-action ├── README.md ├── docs │ ├── Netty-in-Action_en.pdf │ ├── Netty实战.pdf │ └── pics │ │ ├── 3-1.png │ │ ├── 3-3.png │ │ ├── 3-4.png │ │ ├── 4-2.png │ │ ├── 5-1.png │ │ ├── 5-2.png │ │ ├── 5-3.png │ │ ├── 6-3.png │ │ ├── 6-5.png │ │ ├── 7-1.png │ │ ├── 7-2.png │ │ ├── 7-3.png │ │ ├── 7-4.png │ │ ├── 7-5.png │ │ ├── channelWriter.png │ │ ├── table-4-1.png │ │ ├── table-5-1.png │ │ ├── table-5-5.png │ │ ├── table-5-7.png │ │ ├── table-5-8.png │ │ ├── table-6-3.png │ │ ├── table-6-5.png │ │ ├── table-6-8.png │ │ ├── table-6-9.png │ │ └── table4-2.png ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── lwl │ └── netty │ └── chapter │ ├── five │ ├── ByteBufExample.java │ ├── CreateByteBuf.java │ └── CustomByteBufHolder.java │ ├── four │ ├── ChannelOperationExamples.java │ ├── NettyNioServer.java │ ├── NettyOioServer.java │ ├── PlainNioServer.java │ └── PlainOioServer.java │ ├── one │ ├── BlockingIoExample.java │ └── ConnectExample.java │ ├── seven │ └── EventLoopExamples.java │ ├── six │ ├── ChannelFutures.java │ └── OutboundExceptionHandler.java │ └── two │ ├── client │ ├── EchoClient.java │ └── EchoClientHandler.java │ └── server │ ├── EchoServer.java │ └── EchoServerHandler.java ├── netty-practice ├── README.md ├── docs │ └── pics │ │ └── dynamic-ssl.png ├── pom.xml └── src │ └── main │ ├── Resources │ └── log4j2.xml │ └── java │ └── org │ └── lwl │ └── netty │ ├── Config.java │ ├── DynamicDemoStart.java │ ├── UdpDemoStart.java │ ├── comparewrite │ └── Test.java │ ├── core │ ├── CommonUtil.java │ ├── CustomThreadFactory.java │ ├── Decoder.java │ └── Encoder.java │ ├── dynamic │ ├── DynamicConfig.java │ ├── DynamicMsgType.java │ ├── client │ │ ├── DynamicClient.java │ │ ├── DynamicTriggerEvent.java │ │ └── handler │ │ │ ├── ClientInitHandler.java │ │ │ ├── DynamicTriggerHandler.java │ │ │ ├── HeartbeatClientHandler.java │ │ │ ├── ITriggerHandler.java │ │ │ ├── LoginHandler.java │ │ │ ├── RandomCodeHandler.java │ │ │ ├── SslHandler.java │ │ │ └── SymEncryptionHandler.java │ ├── codec │ │ ├── DynamicMsgDecoder.java │ │ ├── DynamicMsgEncoder.java │ │ └── serialize │ │ │ ├── DynamicSerializerFactory.java │ │ │ ├── HeaderSerializer.java │ │ │ ├── IBodySerializer.java │ │ │ ├── TailSerializer.java │ │ │ └── body │ │ │ ├── DefaultBodySerializer.java │ │ │ ├── HtReqBodySerializer.java │ │ │ ├── HtRespBodySerializer.java │ │ │ ├── LoginReqBodySerializer.java │ │ │ ├── LoginRespBodySerializer.java │ │ │ ├── LogoutBodySerializer.java │ │ │ ├── RandomCodeBodySerializer.java │ │ │ ├── SslBodySerializer.java │ │ │ └── SymEncryptionSerializer.java │ ├── message │ │ ├── Body.java │ │ ├── DynamicMessage.java │ │ ├── Header.java │ │ ├── Tail.java │ │ └── body │ │ │ ├── HeartbeatReqBody.java │ │ │ ├── HeartbeatRespBody.java │ │ │ ├── LoginReqBody.java │ │ │ ├── LoginRespBody.java │ │ │ ├── LogoutBody.java │ │ │ ├── RandomCodeBody.java │ │ │ ├── SslBody.java │ │ │ └── SymEncryption.java │ └── server │ │ ├── DynamicServer.java │ │ └── handler │ │ ├── ExceptionHanlder.java │ │ ├── HeartbeatServerHandler.java │ │ ├── LoginRespHandler.java │ │ ├── RandomCodeServerHandler.java │ │ ├── SslServerHandler.java │ │ └── SymEncryptionServerHandler.java │ ├── udp │ └── Test.java │ └── util │ └── Test.java ├── netty-private-protocol ├── README.md ├── docs │ ├── LengthFieldBasedFrameDecoder.md │ └── pics │ │ └── lengthField │ │ ├── lengthField-1.png │ │ ├── lengthField-2.png │ │ ├── lengthField-3.png │ │ ├── lengthField-4.png │ │ ├── lengthField-5.png │ │ └── lengthField-6.png ├── pom.xml └── src │ ├── main │ ├── Resources │ │ ├── bin │ │ │ └── buildProto.sh │ │ ├── data │ │ │ ├── entertainment.txt │ │ │ ├── news.txt │ │ │ └── sports.txt │ │ ├── log4j2.xml │ │ ├── netty-private-protocol.properties │ │ └── proto │ │ │ ├── Body.proto │ │ │ ├── Header.proto │ │ │ ├── HeartbeatReqBody.proto │ │ │ ├── HeartbeatRespBody.proto │ │ │ ├── LoginReqBody.proto │ │ │ ├── LoginRespBody.proto │ │ │ ├── LogoutBody.proto │ │ │ ├── ProtocolDataBody.proto │ │ │ ├── ProtocolMessage.proto │ │ │ ├── ProtocolSubBody.proto │ │ │ └── Tail.proto │ └── java │ │ └── org │ │ └── lwl │ │ └── netty │ │ ├── NettyServerAndClientStart.java │ │ ├── ProtobufServerAndClientStart.java │ │ ├── client │ │ ├── NettyClient.java │ │ ├── NettyClientAdapter.java │ │ ├── ProtobufNettyClient.java │ │ └── handler │ │ │ ├── ClientExceptionHandler.java │ │ │ ├── other │ │ │ ├── HeartbeatClientHandler.java │ │ │ ├── LoginReqHandler.java │ │ │ └── ProtocolMsgSubHandler.java │ │ │ └── protobuf │ │ │ ├── HeartbeatClientHandler.java │ │ │ ├── LoginReqHandler.java │ │ │ ├── ProtobufClientCodecHelper.java │ │ │ └── ProtocolMsgSubHandler.java │ │ ├── codec │ │ ├── other │ │ │ ├── IMessageCodecUtil.java │ │ │ ├── MessageCodecUtilFactory.java │ │ │ ├── ProtocolDataDecoder.java │ │ │ ├── ProtocolDataEncoder.java │ │ │ ├── kryo │ │ │ │ ├── KryoCodecUtil.java │ │ │ │ ├── KryoHolder.java │ │ │ │ ├── KryoReflectionFactory.java │ │ │ │ └── serialize │ │ │ │ │ ├── HeaderKryoSerializer.java │ │ │ │ │ ├── KryoDecoder.java │ │ │ │ │ ├── KryoEncoder.java │ │ │ │ │ ├── ProtocolMessageKryoSerializer.java │ │ │ │ │ ├── TailKryoSerializer.java │ │ │ │ │ └── body │ │ │ │ │ ├── DefaultBodyKryoSerializer.java │ │ │ │ │ ├── HtReqBodyKryoSerializer.java │ │ │ │ │ ├── HtRespBodyKryoSerializer.java │ │ │ │ │ ├── LoginReqBodyKryoSerializer.java │ │ │ │ │ ├── LoginRespBodyKryoSerializer.java │ │ │ │ │ ├── LogoutBodyKryoSerializer.java │ │ │ │ │ ├── ProtocolDataBodyKryoSerializer.java │ │ │ │ │ └── ProtocolSubBodyKryoSerializer.java │ │ │ └── marshalling │ │ │ │ ├── MarshallingAdapterFactory.java │ │ │ │ ├── MarshallingCodecUtil.java │ │ │ │ ├── MarshallingDecoderAdapter.java │ │ │ │ ├── MarshallingEncoderAdapter.java │ │ │ │ ├── MslDecoder.java │ │ │ │ ├── MslEncoder.java │ │ │ │ └── serialize │ │ │ │ ├── HeaderMslSerializer.java │ │ │ │ ├── IBodyMslSerializer.java │ │ │ │ ├── TailMslSerializer.java │ │ │ │ └── body │ │ │ │ ├── DefaultBodyMslSerializer.java │ │ │ │ ├── HeartbeatReqBodyMslSerializer.java │ │ │ │ ├── HeartbeatRespBodyMslSerializer.java │ │ │ │ ├── LoginReqBodyMslSerializer.java │ │ │ │ ├── LoginRespBodyMslSerializer.java │ │ │ │ ├── LogoutBodyMslSerializer.java │ │ │ │ ├── ProtocolDataBodyMslSerializer.java │ │ │ │ └── ProtocolSubBodyMslSerializer.java │ │ └── protobuf │ │ │ └── ProtobufPostDecoder.java │ │ ├── config │ │ ├── BaseConfig.java │ │ └── ProtocolConfig.java │ │ ├── constant │ │ ├── MessageCodecTypeEnum.java │ │ ├── MessageTypeEnum.java │ │ ├── ProtocolConstant.java │ │ └── ProtocolDataType.java │ │ ├── message │ │ ├── Body.java │ │ ├── Header.java │ │ ├── ProtocolMessage.java │ │ ├── Tail.java │ │ ├── body │ │ │ ├── HeartbeatReqBody.java │ │ │ ├── HeartbeatRespBody.java │ │ │ ├── LoginReqBody.java │ │ │ ├── LoginRespBody.java │ │ │ ├── LogoutBody.java │ │ │ ├── ProtocolDataBody.java │ │ │ └── ProtocolSubBody.java │ │ └── protobuf │ │ │ ├── Body.java │ │ │ ├── Header.java │ │ │ ├── HeartbeatReqBody.java │ │ │ ├── HeartbeatRespBody.java │ │ │ ├── LoginReqBody.java │ │ │ ├── LoginRespBody.java │ │ │ ├── LogoutBody.java │ │ │ ├── ProtocolDataBody.java │ │ │ ├── ProtocolMessage.java │ │ │ ├── ProtocolSubBody.java │ │ │ └── Tail.java │ │ ├── server │ │ ├── NettyServer.java │ │ ├── ProtobufNettyServer.java │ │ └── handler │ │ │ ├── ServerExceptionHandler.java │ │ │ ├── other │ │ │ ├── HeartbeatServerHandler.java │ │ │ ├── LoginRespHandler.java │ │ │ └── ProtocolMsgSendHandler.java │ │ │ └── protobuf │ │ │ ├── HeartbeatServerHandler.java │ │ │ ├── LoginRespHandler.java │ │ │ ├── ProtobufServerCodecHelper.java │ │ │ └── ProtocolMsgSendHandler.java │ │ └── util │ │ ├── CommonUtil.java │ │ └── concurrent │ │ └── CustomThreadFactory.java │ └── test │ └── java │ └── org │ └── lwl │ └── netty │ └── start │ ├── NettyClientAndServerStart.java │ ├── NettyClientStart.java │ └── NettyServerStart.java ├── netty-rpc ├── README.md ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── lwl │ │ └── netty │ │ └── Test.java │ └── test │ └── java │ └── org │ └── lwl │ └── netty │ └── Test.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .classpath 3 | .project 4 | *.iml 5 | target/ 6 | .DS_Store 7 | .gitattributes 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # netty 学习 2 | ``` 3 | @author 鲁伟林 4 | 向开源致敬,向优秀前辈代码致敬。 5 | Netty中大量使用NIO技术,满足高性能、高并发要求。进行初步研究,特作此项目。 6 | 7 | 源码地址:https://github.com/thinkingfioa/netty-learning 8 | 本人博客地址: https://blog.csdn.net/thinking_fioa 9 | ``` 10 | 11 | TODO 12 | 13 | 1. 动态编码ChannelHandler 14 | 2. AttributeMap使用 15 | 3. blog: Channel的理解。包括死锁问题 16 | 4. udp项目 17 | 5. Netty 接收缓冲区 18 | 6. Netty实现RPC框架 19 | 7. Netty.4x用户指南 20 | 21 | ## 一、为什么要读Netty? 22 | 23 | ## 1. Netty是什么? 24 | 25 | ## 2. Netty特性 26 | 27 | ## 二、 项目结构介绍 28 | 29 | |序号|名称|介绍| 30 | |:---:|:---:|:---:| 31 | |1|netty-private-protocol|基于Netty自定义私有协议的开发| 32 | |2|netty-in-action|阅读《Netty实战》的笔记,记录诸多Netty的特性和自己的理解| 33 | |3|netty-rpc|使用Netty实现RPC框架| 34 | |4|netty-practice|基于Netty中的诸多特性编写案例,帮助理解| 35 | 36 | ## 1. 私有协议开发(netty-private-protocol) 37 | netty-private-protocol是一个利用Netty实现自定义的协议开发,具有非常高的普世参考价值。参考了《Netty权威指南2》中第12章节。并做以下改进: 38 | 39 | 1.《Netty权威指南2》中第12章节,讲解了关于私有协议栈开发。平时开发中具有参考价值,但书本中代码存在较多问题,本人基于文中代码进行调试,成功运行。 40 | 2.实现了基本私有协议栈开发,并成功运行。在此基础上,比较多种编码和解码的速度。 41 | 3.代码中实现了使用了多种编码和解码逻辑。其中有: Marshalling、Kryo、Protobuf、Thrift和messagePack。通过子项目可以学习基于Netty,实现多种编解码器技术。 42 | 4.[子项目文档地址](https://github.com/thinkingfioa/netty-learning/tree/master/netty-private-protocol) 43 | 44 | ## 2. Netty实战 45 | 《Netty实战》是一本好书。讲解非常透彻,能帮助开发人员更好的理解和使用Netty。最近在读第二遍。推荐此书,讲的非常透彻。 46 | 47 | 1. 总结书中多处知识点,方便开发人员理解和使用。同时添加多处自己的理解。如有错误,请指教 48 | 2. [子项目文档地址](https://github.com/thinkingfioa/netty-learning/tree/master/netty-in-action) 49 | 3. 本书分成多个章节,发布于本人的博客专栏,欢迎各位指出不足之处。[Netty专栏地址](https://blog.csdn.net/column/details/22861.html) 50 | 51 | ## 3. RPC框架实现 52 | 基于Netty,实现基本RPC框架 53 | 54 | ## 4. Netty-Practice 55 | Netty-Practice介绍诸多使用Netty的特性,并辅助案例帮助理解。如: ChannelHandler动态编排、AttributeMap的使用或ChannelPrimise等诸多Netty提供的特性。 56 | 详见(地址)[https://github.com/thinkingfioa/netty-learning/tree/master/netty-practice] 57 | 58 | ## 三、Netty 源码学习 59 | Netty源码研究 60 | 61 | # 参考文档 62 | - 1.《Netty权威指南2》 -------------------------------------------------------------------------------- /netty-in-action/docs/Netty-in-Action_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/Netty-in-Action_en.pdf -------------------------------------------------------------------------------- /netty-in-action/docs/Netty实战.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/Netty实战.pdf -------------------------------------------------------------------------------- /netty-in-action/docs/pics/3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/3-1.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/3-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/3-3.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/3-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/3-4.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/4-2.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/5-1.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/5-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/5-2.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/5-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/5-3.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/6-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/6-3.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/6-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/6-5.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/7-1.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/7-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/7-2.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/7-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/7-3.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/7-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/7-4.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/7-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/7-5.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/channelWriter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/channelWriter.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-4-1.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-5-1.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-5-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-5-5.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-5-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-5-7.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-5-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-5-8.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-6-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-6-3.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-6-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-6-5.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-6-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-6-8.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table-6-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table-6-9.png -------------------------------------------------------------------------------- /netty-in-action/docs/pics/table4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-in-action/docs/pics/table4-2.png -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/five/CreateByteBuf.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.five; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.ByteBufAllocator; 5 | import io.netty.buffer.Unpooled; 6 | import io.netty.channel.ChannelHandlerContext; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/6/24 11 | * @description 12 | */ 13 | 14 | 15 | public class CreateByteBuf { 16 | 17 | public void createByteBuf(ChannelHandlerContext ctx) { 18 | // 1. 通过Channel创建ByteBuf 19 | ByteBuf buf1 = ctx.channel().alloc().buffer(); 20 | // 2. 通过ByteBufAllocator.DEFAULT创建 21 | ByteBuf buf2 = ByteBufAllocator.DEFAULT.buffer(); 22 | // 3. 通过Unpooled创建 23 | ByteBuf buf3 = Unpooled.buffer(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/five/CustomByteBufHolder.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.five; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.DefaultByteBufHolder; 5 | 6 | /** 7 | * 友情提示:建议覆盖DefaultByteBufHolder的所有方法,否则可能出现{@link ClassCastException}
8 | * 希望有更好的方式来实现自定义ByteBuf方式 9 | * 10 | * @author thinking_fioa 11 | * @createTime 2018/6/24 12 | * @description 13 | */ 14 | 15 | 16 | public class CustomByteBufHolder extends DefaultByteBufHolder{ 17 | 18 | private String protocolName; 19 | 20 | public CustomByteBufHolder(String protocolName, ByteBuf data) { 21 | super(data); 22 | this.protocolName = protocolName; 23 | } 24 | 25 | @Override 26 | public CustomByteBufHolder replace(ByteBuf data) { 27 | return new CustomByteBufHolder(protocolName, data); 28 | } 29 | 30 | @Override 31 | public CustomByteBufHolder retain() { 32 | super.retain(); 33 | return this; 34 | } 35 | 36 | @Override 37 | public CustomByteBufHolder touch() { 38 | super.touch(); 39 | return this; 40 | } 41 | 42 | @Override 43 | public CustomByteBufHolder touch(Object hint) { 44 | super.touch(hint); 45 | return this; 46 | } 47 | 48 | public String getProtocolName() { 49 | return protocolName; 50 | } 51 | 52 | public void setProtocolName(String protocolName) { 53 | this.protocolName = protocolName; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/four/ChannelOperationExamples.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.four; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.Channel; 6 | import io.netty.channel.ChannelFuture; 7 | import io.netty.channel.ChannelFutureListener; 8 | import io.netty.channel.socket.nio.NioSocketChannel; 9 | import io.netty.util.CharsetUtil; 10 | 11 | import java.util.concurrent.Executor; 12 | import java.util.concurrent.Executors; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/6/5 17 | * @description 代码清单4-5和4-6 18 | */ 19 | 20 | 21 | public class ChannelOperationExamples { 22 | private static final Channel CHANNEL_FROM_SOMEWHERE = new NioSocketChannel(); 23 | 24 | /** 25 | * 代码清单4-5 往Channel中写 26 | */ 27 | public static void writingToChannel() { 28 | Channel channel = CHANNEL_FROM_SOMEWHERE; 29 | ByteBuf buf = Unpooled.copiedBuffer("your data", CharsetUtil.UTF_8); 30 | ChannelFuture cf = channel.writeAndFlush(buf); 31 | cf.addListener(new ChannelFutureListener() { 32 | @Override 33 | public void operationComplete(ChannelFuture future) { 34 | if (future.isSuccess()) { 35 | System.out.println("Write successful"); 36 | } else { 37 | System.err.println("Write error"); 38 | future.cause().printStackTrace(); 39 | } 40 | } 41 | }); 42 | } 43 | 44 | /** 45 | * 代码清单4-6 多个线程同时访问同一个Channel。 46 | * 1. Channel是线程安全。 47 | * 2. 消息将严格按照顺序发送 48 | */ 49 | public static void writingToChannelFromManyThreads() { 50 | final Channel channel = CHANNEL_FROM_SOMEWHERE; 51 | final ByteBuf buf = Unpooled.copiedBuffer("your data", CharsetUtil.UTF_8); 52 | Runnable writer = new Runnable() { 53 | @Override 54 | public void run() { 55 | channel.write(buf.duplicate()); 56 | } 57 | }; 58 | Executor executor = Executors.newCachedThreadPool(); 59 | 60 | // write in one thread 61 | executor.execute(writer); 62 | 63 | // write in another thread 64 | executor.execute(writer); 65 | //... 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/four/NettyNioServer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.four; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.buffer.Unpooled; 6 | import io.netty.channel.*; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.SocketChannel; 9 | import io.netty.channel.socket.nio.NioServerSocketChannel; 10 | import io.netty.channel.socket.oio.OioServerSocketChannel; 11 | 12 | import java.net.InetSocketAddress; 13 | import java.nio.charset.Charset; 14 | 15 | /** 16 | * @author thinking_fioa 17 | * @createTime 2018/5/27 18 | * @description 代码清单4-4,Netty非阻塞网络编程 19 | */ 20 | 21 | 22 | public class NettyNioServer { 23 | public void server(int port) 24 | throws Exception { 25 | final ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8"))); 26 | /** 27 | * 与Netty的BIO第一处不同 28 | */ 29 | EventLoopGroup group = new NioEventLoopGroup(); 30 | try { 31 | ServerBootstrap b = new ServerBootstrap(); 32 | /** 33 | * 与Netty的BIO第二处不同 34 | */ 35 | b.group(group).channel(NioServerSocketChannel.class) 36 | .localAddress(new InetSocketAddress(port)) 37 | .childHandler(new ChannelInitializer() { 38 | @Override 39 | public void initChannel(SocketChannel ch) throws Exception { 40 | ch.pipeline().addLast( new ChannelInboundHandlerAdapter() { 41 | @Override 42 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 43 | ctx.writeAndFlush(buf.duplicate()) 44 | .addListener(ChannelFutureListener.CLOSE); 45 | } 46 | }); 47 | } 48 | }); 49 | ChannelFuture f = b.bind().sync(); 50 | f.channel().closeFuture().sync(); 51 | } finally { 52 | group.shutdownGracefully().sync(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/four/NettyOioServer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.four; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.buffer.Unpooled; 6 | import io.netty.channel.*; 7 | import io.netty.channel.oio.OioEventLoopGroup; 8 | import io.netty.channel.socket.SocketChannel; 9 | import io.netty.channel.socket.oio.OioServerSocketChannel; 10 | 11 | import java.net.InetSocketAddress; 12 | import java.nio.charset.Charset; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/5/27 17 | * @description 代码清单4-3,Netty阻塞网络编程 18 | */ 19 | 20 | 21 | public class NettyOioServer { 22 | public void server(int port) 23 | throws Exception { 24 | final ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8"))); 25 | /** 26 | * 与Netty的NIO第一处不同 27 | */ 28 | EventLoopGroup group = new OioEventLoopGroup(); 29 | try { 30 | ServerBootstrap b = new ServerBootstrap(); 31 | /** 32 | * 与Netty的NIO第二处不同 33 | */ 34 | b.group(group).channel(OioServerSocketChannel.class) 35 | .localAddress(new InetSocketAddress(port)) 36 | .childHandler(new ChannelInitializer() { 37 | @Override 38 | public void initChannel(SocketChannel ch) throws Exception { 39 | ch.pipeline().addLast( new ChannelInboundHandlerAdapter() { 40 | @Override 41 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 42 | ctx.writeAndFlush(buf.duplicate()) 43 | .addListener(ChannelFutureListener.CLOSE); 44 | } 45 | }); 46 | } 47 | }); 48 | ChannelFuture f = b.bind().sync(); 49 | f.channel().closeFuture().sync(); 50 | } finally { 51 | group.shutdownGracefully().sync(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/four/PlainOioServer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.four; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.net.ServerSocket; 6 | import java.net.Socket; 7 | import java.nio.charset.Charset; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/27 12 | * @description 代码清单4-1,Java原生的阻塞网络编程 13 | */ 14 | 15 | 16 | public class PlainOioServer { 17 | public void serve(int port) throws IOException { 18 | final ServerSocket socket = new ServerSocket(port); 19 | try { 20 | for(;;) { 21 | final Socket clientSocket = socket.accept(); 22 | System.out.println( 23 | "Accepted connection from " + clientSocket); 24 | new Thread(new Runnable() { 25 | @Override 26 | public void run() { 27 | OutputStream out; 28 | try { 29 | out = clientSocket.getOutputStream(); 30 | out.write("Hi!\r\n".getBytes( 31 | Charset.forName("UTF-8"))); 32 | out.flush(); 33 | clientSocket.close(); 34 | } catch (IOException e) { 35 | e.printStackTrace(); 36 | } finally { 37 | try { 38 | clientSocket.close(); 39 | } catch (IOException ex) { 40 | // ignore on close 41 | } 42 | } 43 | } 44 | }).start(); 45 | } 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/one/BlockingIoExample.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.one; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.PrintWriter; 7 | import java.net.ServerSocket; 8 | import java.net.Socket; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/5/14 13 | * @description BIO 服务端例子, 代码清单 1-1 阻塞I/O示例 14 | */ 15 | 16 | 17 | public class BlockingIoExample { 18 | 19 | public void serve(int port) throws IOException { 20 | ServerSocket serverSocket = new ServerSocket(port); 21 | Socket clientSocket = serverSocket.accept(); 22 | BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 23 | PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); 24 | String request, response; 25 | while((request = in.readLine()) != null) { 26 | if("Done".equals(request)) { 27 | break; 28 | } 29 | response = processRequest(request); 30 | out.println(response); 31 | } 32 | } 33 | 34 | private String processRequest(String request) { 35 | return "Processed"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/one/ConnectExample.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.one; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.Channel; 6 | import io.netty.channel.ChannelFuture; 7 | import io.netty.channel.ChannelFutureListener; 8 | import io.netty.channel.socket.nio.NioSocketChannel; 9 | 10 | import java.net.InetSocketAddress; 11 | import java.nio.charset.Charset; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/5/16 16 | * @description 代码清单1-3/1-4。 连接建立+回调函数 17 | */ 18 | 19 | 20 | public class ConnectExample { 21 | private static final Channel CHANNEL_FROM_SOMEWHERE = new NioSocketChannel(); 22 | 23 | public static void connect() { 24 | Channel channel = CHANNEL_FROM_SOMEWHERE; 25 | 26 | ChannelFuture future = channel.connect(new InetSocketAddress("127.0.0.1", 9080)); 27 | future.addListener(new ChannelFutureListener() { 28 | @Override 29 | public void operationComplete(ChannelFuture future) throws Exception { 30 | if(future.isSuccess()) { 31 | ByteBuf buf = Unpooled.copiedBuffer("hello", Charset.defaultCharset()); 32 | ChannelFuture wf = future.channel().writeAndFlush(buf); 33 | // ... 34 | } else { 35 | future.cause().printStackTrace(); 36 | } 37 | } 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/seven/EventLoopExamples.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.seven; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/8/14 9 | * @description 10 | */ 11 | 12 | 13 | public class EventLoopExamples { 14 | /** 15 | * 代码清单 7-1 16 | */ 17 | public static void executeTaskInEventLoop() { 18 | boolean terminated = true; 19 | 20 | while (!terminated) { 21 | List readyEvents = blockUntilEventsReady(); 22 | for (Runnable ev: readyEvents) { 23 | ev.run(); 24 | } 25 | } 26 | } 27 | 28 | public static List blockUntilEventsReady() { 29 | return new ArrayList<>(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/six/ChannelFutures.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.six; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.Channel; 6 | import io.netty.channel.ChannelFuture; 7 | import io.netty.channel.ChannelHandlerContext; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/7/15 12 | * @description 代码清单6-13。添加ChannelFutureListener到ChannelFuture 13 | */ 14 | 15 | 16 | public class ChannelFutures { 17 | public static void addingChannelFutureListener(ChannelHandlerContext ctx){ 18 | Channel channel = ctx.channel(); 19 | ByteBuf someMessage = Unpooled.buffer(); 20 | //... 21 | io.netty.channel.ChannelFuture future = channel.write(someMessage); 22 | future.addListener((ChannelFuture f) -> { 23 | if(f.isSuccess()) { 24 | // operation success. 25 | System.out.println("success."); 26 | }else { 27 | // operation fail 28 | f.cause().printStackTrace(); 29 | } 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/six/OutboundExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.six; 2 | 3 | import io.netty.channel.ChannelFuture; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.ChannelOutboundHandlerAdapter; 6 | import io.netty.channel.ChannelPromise; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/7/15 11 | * @description 代码清单6-14,添加ChannelFutureListener到ChannelPromise 12 | */ 13 | 14 | public class OutboundExceptionHandler extends ChannelOutboundHandlerAdapter{ 15 | 16 | @Override 17 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { 18 | ctx.write(msg, promise); 19 | promise.addListener((ChannelFuture f) -> { 20 | if (f.isSuccess()) { 21 | // operation success. 22 | System.out.println("success."); 23 | }else { 24 | // operation fail 25 | f.cause().printStackTrace(); 26 | } 27 | }); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/two/client/EchoClient.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.two.client; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.ChannelFuture; 5 | import io.netty.channel.ChannelInitializer; 6 | import io.netty.channel.EventLoopGroup; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.SocketChannel; 9 | import io.netty.channel.socket.nio.NioSocketChannel; 10 | 11 | import java.net.InetSocketAddress; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/5/16 16 | * @description 代码清单 2-4,客户端引导类 17 | */ 18 | 19 | 20 | public class EchoClient { 21 | private final String host; 22 | private final int port; 23 | 24 | public EchoClient(String host, int port) { 25 | this.host = host; 26 | this.port = port; 27 | } 28 | 29 | public void start() 30 | throws Exception { 31 | EventLoopGroup group = new NioEventLoopGroup(); 32 | try { 33 | Bootstrap b = new Bootstrap(); 34 | b.group(group) 35 | .channel(NioSocketChannel.class) 36 | .remoteAddress(new InetSocketAddress(host, port)) 37 | .handler(new ChannelInitializer() { 38 | @Override 39 | public void initChannel(SocketChannel ch) 40 | throws Exception { 41 | ch.pipeline().addLast( 42 | new EchoClientHandler()); 43 | } 44 | }); 45 | // 下面两行代码可以删除 46 | ChannelFuture f = b.connect().sync(); 47 | f.channel().closeFuture().sync(); 48 | } finally { 49 | group.shutdownGracefully().sync(); 50 | } 51 | } 52 | 53 | public static void main(String[] args) throws Exception { 54 | 55 | new EchoClient("127.0.0.1", 9080).start(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/two/client/EchoClientHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.two.client; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.SimpleChannelInboundHandler; 7 | import io.netty.util.CharsetUtil; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/21 12 | * @description 代码清单2-3 客户端业务处理Handler 13 | */ 14 | 15 | 16 | public class EchoClientHandler extends SimpleChannelInboundHandler { 17 | 18 | /** 19 | * 链路激活事件 20 | */ 21 | @Override 22 | public void channelActive(ChannelHandlerContext ctx) { 23 | ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", 24 | CharsetUtil.UTF_8)); 25 | } 26 | 27 | /** 28 | * 有消息读取 29 | * @param ctx 30 | * @param in 31 | */ 32 | @Override 33 | public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) { 34 | System.out.println( 35 | "Client received: " + in.toString(CharsetUtil.UTF_8)); 36 | } 37 | 38 | @Override 39 | public void exceptionCaught(ChannelHandlerContext ctx, 40 | Throwable cause) { 41 | cause.printStackTrace(); 42 | ctx.close(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/two/server/EchoServer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.two.server; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.ChannelFuture; 5 | import io.netty.channel.ChannelInitializer; 6 | import io.netty.channel.EventLoopGroup; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.SocketChannel; 9 | import io.netty.channel.socket.nio.NioServerSocketChannel; 10 | 11 | import java.net.InetSocketAddress; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/5/16 16 | * @description 代码清单 2-2,服务端引导器 17 | */ 18 | 19 | 20 | public class EchoServer { 21 | private final int port; 22 | 23 | public EchoServer(int port) { 24 | this.port = port; 25 | } 26 | 27 | public static void main(String[] args) 28 | throws Exception { 29 | 30 | int port = 9080; 31 | new EchoServer(port).start(); 32 | } 33 | 34 | public void start() throws Exception { 35 | EventLoopGroup group = new NioEventLoopGroup(); 36 | try { 37 | ServerBootstrap b = new ServerBootstrap(); 38 | b.group(group) 39 | .channel(NioServerSocketChannel.class) 40 | .localAddress(new InetSocketAddress(port)) 41 | .childHandler(new ChannelInitializer() { 42 | @Override 43 | public void initChannel(SocketChannel ch) throws Exception { 44 | ch.pipeline().addLast(new EchoServerHandler()); 45 | } 46 | }); 47 | // 实际项目中,b.bind().sync()可以省略 48 | ChannelFuture f = b.bind().sync(); 49 | System.out.println(EchoServer.class.getName() + 50 | " started and listening for connections on " + f.channel().localAddress()); 51 | // 实际项目中,f.channel().closeFuture().sync()可以省略 52 | f.channel().closeFuture().sync(); 53 | } finally { 54 | group.shutdownGracefully().sync(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /netty-in-action/src/main/java/org/lwl/netty/chapter/two/server/EchoServerHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.chapter.two.server; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.ChannelFutureListener; 6 | import io.netty.channel.ChannelHandler; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.channel.ChannelInboundHandlerAdapter; 9 | import io.netty.util.CharsetUtil; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/5/21 14 | * @description 代码清单 2-1,服务端处理Handler 15 | */ 16 | 17 | @ChannelHandler.Sharable 18 | public class EchoServerHandler extends ChannelInboundHandlerAdapter{ 19 | 20 | /** 21 | * 每次传入的消息都要调用 22 | */ 23 | @Override 24 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 25 | ByteBuf in = (ByteBuf) msg; 26 | System.out.println( 27 | "Server received: " + in.toString(CharsetUtil.UTF_8)); 28 | ctx.write(in); 29 | } 30 | 31 | /** 32 | * 读完当前批量中的最后一条数据后,触发channelReadComplete(...)方法 33 | */ 34 | @Override 35 | public void channelReadComplete(ChannelHandlerContext ctx) 36 | throws Exception { 37 | ctx.writeAndFlush(Unpooled.EMPTY_BUFFER) 38 | .addListener(ChannelFutureListener.CLOSE); 39 | } 40 | 41 | /** 42 | * 异常捕获 43 | */ 44 | @Override 45 | public void exceptionCaught(ChannelHandlerContext ctx, 46 | Throwable cause) { 47 | cause.printStackTrace(); 48 | ctx.close(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /netty-practice/docs/pics/dynamic-ssl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-practice/docs/pics/dynamic-ssl.png -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/Config.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty; 2 | 3 | import java.nio.charset.Charset; 4 | 5 | /** 6 | * @author thinking_fioa 7 | * @createTime 2018/7/28 8 | * @description 9 | */ 10 | 11 | 12 | public final class Config { 13 | private Config() { 14 | throw new IllegalAccessError("static class, can not constructor."); 15 | } 16 | 17 | public static String getCharsetFormatStr() { 18 | return "UTF-8"; 19 | } 20 | 21 | public static Charset getCharsetFormat() { 22 | return Charset.forName(getCharsetFormatStr()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/DynamicDemoStart.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty; 2 | 3 | import org.lwl.netty.dynamic.client.DynamicClient; 4 | import org.lwl.netty.dynamic.server.DynamicServer; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/7/11 9 | * @description 动态编排ChannelHandler的启动main 10 | */ 11 | 12 | 13 | public class DynamicDemoStart { 14 | 15 | public static void main(String [] args) throws InterruptedException { 16 | // Dynamic服务端以单个线程启动 17 | new Thread(new Runnable() { 18 | @Override 19 | public void run() { 20 | new DynamicServer().start(); 21 | } 22 | }).start(); 23 | 24 | Thread.sleep(6000); 25 | 26 | // Dynamic客户端以单个线程启动 27 | new Thread(new Runnable() { 28 | @Override 29 | public void run() { 30 | new DynamicClient().start(); 31 | } 32 | }).start(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/UdpDemoStart.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/7/23 6 | * @description Udp案例启动类 7 | */ 8 | 9 | 10 | public class UdpDemoStart { 11 | public static void main() { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/comparewrite/Test.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.comparewrite; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/7/25 6 | * @description 7 | */ 8 | 9 | 10 | public class Test { 11 | } 12 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/core/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.core; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | 5 | import java.time.LocalDateTime; 6 | import java.time.format.DateTimeFormatter; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/7/28 11 | * @description 12 | */ 13 | 14 | 15 | public class CommonUtil { 16 | private CommonUtil() { 17 | throw new IllegalAccessError("can not use constructor about static class"); 18 | } 19 | 20 | /** 21 | * 计算checkSum 22 | * @return 23 | */ 24 | public static int calCheckSum(ByteBuf byteBuf, int length) { 25 | if(length <=0) { 26 | throw new IllegalArgumentException("length <= 0"); 27 | } 28 | byte checkSum = 0; 29 | length = Math.min(length, byteBuf.writerIndex()); 30 | for(int i = 0; i value == null, 写入-1. 2> value == "", 写入0. 17 | */ 18 | public static void writeString(ByteBuf outByteBuf, String value) { 19 | if(null == value) { 20 | outByteBuf.writeInt(-1); 21 | 22 | return ; 23 | } 24 | 25 | if(value.isEmpty()) { 26 | outByteBuf.writeInt(0); 27 | 28 | return; 29 | } 30 | byte[] valueBytes = value.getBytes(Config.getCharsetFormat()); 31 | outByteBuf.writeInt(valueBytes.length); 32 | outByteBuf.writeBytes(valueBytes); 33 | } 34 | 35 | public static void writeBytes(ByteBuf outByteBuf, byte[] bytes) { 36 | outByteBuf.writeBytes(bytes); 37 | } 38 | 39 | /** 40 | * 序列化{@code Integer} 值 41 | */ 42 | public static void writeInt(ByteBuf outByteBuf, int value) { 43 | outByteBuf.writeInt(value); 44 | } 45 | 46 | public static void writeLong(ByteBuf outByteBuf, long value) { 47 | outByteBuf.writeLong(value); 48 | } 49 | 50 | public static void writeByte(ByteBuf outByteBuf, byte value) { 51 | outByteBuf.writeByte(value); 52 | } 53 | 54 | public static void writeDouble(ByteBuf outByteBuf, double value) { 55 | outByteBuf.writeDouble(value); 56 | } 57 | 58 | public static void writeShort(ByteBuf outByteBuf, short value) { 59 | outByteBuf.writeShort(value); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/DynamicConfig.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/8/6 6 | * @description 7 | */ 8 | 9 | 10 | public class DynamicConfig { 11 | private DynamicConfig() { 12 | throw new UnsupportedOperationException("static class"); 13 | } 14 | 15 | public static String getUserName() { 16 | return "thinking"; 17 | } 18 | 19 | public static String getPasswd() { 20 | return "fioa"; 21 | } 22 | 23 | public static String getSslVersion() { 24 | return "3.2.2"; 25 | } 26 | 27 | public static String getSymEncryption() { 28 | return "AES"; 29 | } 30 | 31 | public static int getHtMultiple() { 32 | return 6; 33 | } 34 | 35 | public static String getServerIp() { 36 | return "127.0.0.1"; 37 | } 38 | 39 | public static int getPort() { 40 | return 8989; 41 | } 42 | 43 | public static long getHtInterval() { 44 | return 5; 45 | } 46 | 47 | public static int getMaxFramelength() { 48 | // 4K 49 | return 4 * 1024; 50 | } 51 | 52 | public static int getLengthFieldOffset() { 53 | return 0; 54 | } 55 | 56 | public static int getLengthfieldLength() { 57 | return 4; 58 | } 59 | 60 | public static int getLengthAdjustment() { 61 | return -4; 62 | } 63 | 64 | public static int getInitialBytesToStrip() { 65 | return 0; 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/DynamicMsgType.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/7/28 9 | * @description 10 | */ 11 | 12 | 13 | public enum DynamicMsgType { 14 | 15 | /** 16 | * Unknown 消息类型 17 | */ 18 | UNKNOWN((byte)0, "unknown"), 19 | 20 | /** 21 | * SSL版本信息 22 | */ 23 | SSL((byte)1, "SSL"), 24 | 25 | /** 26 | * 对称加密 27 | */ 28 | SYM_ENCRYPTION((byte)2, "SymEncryption"), 29 | 30 | /** 31 | * 随机数生成密钥 32 | */ 33 | RANDOM_CODE((byte)3, "RandomCode"), 34 | 35 | /** 36 | * 登陆消息 37 | */ 38 | LOGIN_REQ((byte)4, "loginReq"), 39 | 40 | /** 41 | * 登陆响应 42 | */ 43 | LOGIN_RESP((byte)5, "loginResp"), 44 | 45 | /** 46 | * 注销 47 | */ 48 | LOGOUT((byte)6, "logout"), 49 | 50 | /** 51 | * 心跳请求 52 | */ 53 | HEARTBEAT_REQ((byte)7, "heartbeatReq"), 54 | 55 | /** 56 | * 心跳响应 57 | */ 58 | HEARTBEAT_RESP((byte)8, "heartbeatResp"); 59 | 60 | 61 | private final byte msgType; 62 | private final String desc; 63 | 64 | DynamicMsgType(byte msgType, String desc) { 65 | this.msgType = msgType; 66 | this.desc = desc; 67 | } 68 | 69 | /** 70 | * 根据msgType类型,获取{@code DynamicMsgType}
71 | * 使用Hashmap缓存,提高缓存 72 | * @param msgType 73 | * @return 74 | */ 75 | public static DynamicMsgType getMsgTypeEnum(final Byte msgType) { 76 | if(null == msgType ) { 77 | return null; 78 | } 79 | 80 | return DynamicMsgTypeHolder.getMsgTypeEnum(msgType); 81 | } 82 | 83 | public byte getMsgType() { 84 | return msgType; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return desc; 90 | } 91 | 92 | private static class DynamicMsgTypeHolder { 93 | private static Map msgTypeMap; 94 | static { 95 | msgTypeMap = new HashMap<>(); 96 | for(DynamicMsgType type: DynamicMsgType.values()) { 97 | msgTypeMap.put(type.getMsgType(), type); 98 | } 99 | } 100 | 101 | public static DynamicMsgType getMsgTypeEnum(Byte key) { 102 | if(msgTypeMap.containsKey(key)) { 103 | return msgTypeMap.get(key); 104 | } 105 | return null; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/DynamicClient.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.ChannelInitializer; 5 | import io.netty.channel.EventLoopGroup; 6 | import io.netty.channel.nio.NioEventLoopGroup; 7 | import io.netty.channel.socket.SocketChannel; 8 | import io.netty.channel.socket.nio.NioSocketChannel; 9 | import org.apache.logging.log4j.LogManager; 10 | import org.apache.logging.log4j.Logger; 11 | import org.lwl.netty.core.CustomThreadFactory; 12 | import org.lwl.netty.dynamic.DynamicConfig; 13 | import org.lwl.netty.dynamic.client.handler.ClientInitHandler; 14 | import org.lwl.netty.dynamic.client.handler.DynamicTriggerHandler; 15 | import org.lwl.netty.dynamic.codec.DynamicMsgDecoder; 16 | import org.lwl.netty.dynamic.codec.DynamicMsgEncoder; 17 | 18 | /** 19 | * @author thinking_fioa 20 | * @createTime 2018/7/28 21 | * @description 22 | */ 23 | 24 | 25 | public class DynamicClient { 26 | private static final Logger LOGGER = LogManager.getLogger(DynamicClient.class); 27 | 28 | private EventLoopGroup group = new NioEventLoopGroup(1, new CustomThreadFactory("DynamicClientGroup", true)); 29 | 30 | private void connect(String ip, int port) { 31 | Bootstrap bootstrap = new Bootstrap(); 32 | bootstrap.group(group).channel(NioSocketChannel.class) 33 | .handler(new ChildChannelHandler()); 34 | bootstrap.connect(ip, port).addListener((future) -> { 35 | if(future.isSuccess()) { 36 | LOGGER.info("connect {}:{} success.", ip, port); 37 | } else { 38 | LOGGER.error("connect {}:{} fail",ip, port, future.cause()); 39 | } 40 | }); 41 | } 42 | 43 | public void start() { 44 | connect(DynamicConfig.getServerIp(), DynamicConfig.getPort()); 45 | } 46 | 47 | public void quit() { 48 | if(null != group) { 49 | group.shutdownGracefully(); 50 | } 51 | } 52 | 53 | private static class ChildChannelHandler extends ChannelInitializer { 54 | @Override 55 | protected void initChannel(SocketChannel ch) throws Exception { 56 | // 初始化只有4个Handler,其他的Handler动态加入到Pipeline 57 | ch.pipeline().addLast(new DynamicMsgDecoder()); 58 | ch.pipeline().addLast(new DynamicMsgEncoder()); 59 | ch.pipeline().addLast(new ClientInitHandler()); 60 | ch.pipeline().addLast(DynamicTriggerHandler.class.getSimpleName(), new DynamicTriggerHandler()); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/ClientInitHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.client.DynamicTriggerEvent; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/7/28 12 | * @description 13 | */ 14 | 15 | 16 | public class ClientInitHandler extends ChannelInboundHandlerAdapter{ 17 | private static final Logger LOGGER = LogManager.getLogger(ClientInitHandler.class); 18 | 19 | @Override 20 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 21 | LOGGER.info("active channel {}", ctx.channel().remoteAddress()); 22 | ctx.fireUserEventTriggered(DynamicTriggerEvent.SSL_EVENT); 23 | } 24 | 25 | @Override 26 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 27 | LOGGER.info("inactive channel {}", ctx.channel().remoteAddress()); 28 | ctx.fireChannelInactive(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/DynamicTriggerHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.client.DynamicTriggerEvent; 8 | 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/8/6 13 | * @description 动态添加Handler 14 | */ 15 | 16 | 17 | public class DynamicTriggerHandler extends ChannelInboundHandlerAdapter{ 18 | 19 | private static final Logger LOGGER = LogManager.getLogger(DynamicTriggerHandler.class); 20 | 21 | @Override 22 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 23 | if(evt instanceof DynamicTriggerEvent) { 24 | DynamicTriggerEvent triggerEvent = (DynamicTriggerEvent)evt; 25 | LOGGER.info("trigger DynamicTrigger {}", triggerEvent); 26 | 27 | triggerEvent.trigger(ctx, DynamicTriggerHandler.class); 28 | } else { 29 | super.userEventTriggered(ctx, evt); 30 | } 31 | } 32 | 33 | @Override 34 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 35 | throws Exception { 36 | LOGGER.error("happen unknown exception.", cause); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/HeartbeatClientHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import io.netty.handler.timeout.IdleState; 6 | import io.netty.handler.timeout.IdleStateEvent; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | import org.lwl.netty.dynamic.DynamicConfig; 10 | import org.lwl.netty.dynamic.DynamicMsgType; 11 | import org.lwl.netty.dynamic.message.DynamicMessage; 12 | import org.lwl.netty.dynamic.message.body.HeartbeatReqBody; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/7/28 17 | * @description 18 | */ 19 | 20 | 21 | public class HeartbeatClientHandler extends ChannelInboundHandlerAdapter implements ITriggerHandler{ 22 | private static final Logger LOGGER = LogManager.getLogger(HeartbeatClientHandler.class); 23 | private int lossConnectTime = 0; 24 | 25 | @Override 26 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 27 | if(evt instanceof IdleStateEvent) { 28 | IdleStateEvent event = (IdleStateEvent)evt; 29 | if(event.state() == IdleState.READER_IDLE) { 30 | lossConnectTime ++; 31 | if(lossConnectTime > DynamicConfig.getHtMultiple()) { 32 | LOGGER.error("heartbeat timeout. close channel {}", ctx.channel().remoteAddress()); 33 | ctx.close(); 34 | return; 35 | } 36 | } else if(event.state() == IdleState.WRITER_IDLE) { 37 | LOGGER.warn("heartbeat timeout. lossCount {}", lossConnectTime); 38 | ctx.writeAndFlush(buildHtReqMsg()); 39 | } 40 | } else { 41 | ctx.fireUserEventTriggered(evt); 42 | } 43 | } 44 | 45 | @Override 46 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 47 | DynamicMessage message = (DynamicMessage) msg; 48 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 49 | lossConnectTime = 0; 50 | if(DynamicMsgType.HEARTBEAT_RESP.equals(msgType)) { 51 | LOGGER.debug("receive heartbeat resp"); 52 | return; 53 | } else { 54 | ctx.fireChannelRead(msg); 55 | } 56 | } 57 | 58 | private DynamicMessage buildHtReqMsg() { 59 | HeartbeatReqBody htReqBody = new HeartbeatReqBody(); 60 | 61 | return DynamicMessage.createMsgOfEncode(htReqBody); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/ITriggerHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | 5 | /** 6 | * @author thinking_fioa 7 | * @createTime 2018/8/12 8 | * @description 9 | */ 10 | 11 | 12 | public interface ITriggerHandler { 13 | default void launch(ChannelHandlerContext ctx) { 14 | //do nothing 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/LoginHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.DynamicConfig; 8 | import org.lwl.netty.dynamic.DynamicMsgType; 9 | import org.lwl.netty.dynamic.client.DynamicTriggerEvent; 10 | import org.lwl.netty.dynamic.message.DynamicMessage; 11 | import org.lwl.netty.dynamic.message.body.LoginReqBody; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/7/28 16 | * @description 发送登录请求 17 | */ 18 | 19 | 20 | public class LoginHandler extends ChannelInboundHandlerAdapter implements ITriggerHandler{ 21 | private static final Logger LOGGER = LogManager.getLogger(LoginHandler.class); 22 | 23 | private final String USERNAME = DynamicConfig.getUserName(); 24 | private final String PASSWD = DynamicConfig.getPasswd(); 25 | 26 | @Override 27 | public void launch(ChannelHandlerContext ctx) { 28 | LOGGER.info("login sent."); 29 | ctx.writeAndFlush(buildLoginReqBody()); 30 | } 31 | 32 | @Override 33 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 34 | DynamicMessage message = (DynamicMessage) msg; 35 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 36 | if(DynamicMsgType.LOGIN_RESP.equals(msgType)) { 37 | // 客户端接收到登录响应,启动心跳 38 | LOGGER.info("receive login resp. launch heartbeat."); 39 | ctx.fireUserEventTriggered(DynamicTriggerEvent.HEARTBEAT_EVENT); 40 | } else { 41 | ctx.fireChannelRead(msg); 42 | } 43 | } 44 | 45 | private DynamicMessage buildLoginReqBody() { 46 | LoginReqBody loginReqBody = new LoginReqBody(); 47 | loginReqBody.setUserName(USERNAME); 48 | loginReqBody.setPassword(PASSWD); 49 | 50 | return DynamicMessage.createMsgOfEncode(loginReqBody); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/RandomCodeHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.message.DynamicMessage; 8 | import org.lwl.netty.dynamic.message.body.RandomCodeBody; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/7/28 13 | * @description 产生随机码,使用服务端密钥加密后,发送至服务器 14 | */ 15 | 16 | 17 | public class RandomCodeHandler extends ChannelInboundHandlerAdapter implements ITriggerHandler{ 18 | private static final Logger LOGGER = LogManager.getLogger(RandomCodeHandler.class); 19 | 20 | private static final String RANDOM_CODE = "luweilin"; 21 | 22 | @Override 23 | public void launch(ChannelHandlerContext ctx) { 24 | LOGGER.info("randomCode sent."); 25 | ctx.writeAndFlush(buildRandomCodeBody()); 26 | // 发起登录请求 27 | LoginHandler loginHandler = new LoginHandler(); 28 | ctx.pipeline().addBefore(DynamicTriggerHandler.class.getSimpleName(), LoginHandler.class.getSimpleName(), loginHandler); 29 | loginHandler.launch(ctx); 30 | } 31 | 32 | private DynamicMessage buildRandomCodeBody() { 33 | RandomCodeBody randomCodeBody = new RandomCodeBody(); 34 | randomCodeBody.setRandomCode(RANDOM_CODE); 35 | 36 | return DynamicMessage.createMsgOfEncode(randomCodeBody); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/SslHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.DynamicConfig; 8 | import org.lwl.netty.dynamic.DynamicMsgType; 9 | import org.lwl.netty.dynamic.client.DynamicTriggerEvent; 10 | import org.lwl.netty.dynamic.message.DynamicMessage; 11 | import org.lwl.netty.dynamic.message.body.SslBody; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/7/28 16 | * @description 发送Client端的SSL版本信息 17 | */ 18 | 19 | 20 | public class SslHandler extends ChannelInboundHandlerAdapter implements ITriggerHandler{ 21 | private static final Logger LOGGER = LogManager.getLogger(SslHandler.class); 22 | 23 | private static final String SSL_VERSION = DynamicConfig.getSslVersion(); 24 | 25 | @Override 26 | public void launch(ChannelHandlerContext ctx) { 27 | LOGGER.info("ssl sent."); 28 | ctx.writeAndFlush(buildSslBody()); 29 | } 30 | 31 | @Override 32 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 33 | DynamicMessage message = (DynamicMessage) msg; 34 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 35 | if(DynamicMsgType.SSL.equals(msgType)) { 36 | // 客户端接收到ssl消息后,启动对称加密Handler 37 | LOGGER.info("receive ssl resp. launch symEncryption."); 38 | ctx.fireUserEventTriggered(DynamicTriggerEvent.SYM_ENCRYPTION_EVENT); 39 | } else { 40 | ctx.fireChannelRead(msg); 41 | } 42 | } 43 | 44 | private DynamicMessage buildSslBody() { 45 | SslBody sslBody = new SslBody(); 46 | sslBody.setSslVersion(SSL_VERSION); 47 | 48 | return DynamicMessage.createMsgOfEncode(sslBody); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/client/handler/SymEncryptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.DynamicConfig; 8 | import org.lwl.netty.dynamic.DynamicMsgType; 9 | import org.lwl.netty.dynamic.client.DynamicTriggerEvent; 10 | import org.lwl.netty.dynamic.message.DynamicMessage; 11 | import org.lwl.netty.dynamic.message.body.SymEncryption; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/7/28 16 | * @description 发送Client端支持的对称加密方案 17 | */ 18 | 19 | 20 | public class SymEncryptionHandler extends ChannelInboundHandlerAdapter implements ITriggerHandler{ 21 | private static final Logger LOGGER = LogManager.getLogger(SymEncryptionHandler.class); 22 | 23 | private static final String SYM_ENCRYPTION = DynamicConfig.getSymEncryption(); 24 | 25 | @Override 26 | public void launch(ChannelHandlerContext ctx) { 27 | LOGGER.info("symEncryption sent."); 28 | ctx.writeAndFlush(buildSymEncryption()); 29 | } 30 | 31 | @Override 32 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 33 | DynamicMessage message = (DynamicMessage) msg; 34 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 35 | if(DynamicMsgType.SYM_ENCRYPTION.equals(msgType)) { 36 | // 客户端接收到symEncryption消息后,启动随机数加密Handler 37 | LOGGER.info("receive symEncryption resp. launch randomCode."); 38 | ctx.fireUserEventTriggered(DynamicTriggerEvent.RANDOM_CODE_EVENT); 39 | } else { 40 | ctx.fireChannelRead(msg); 41 | } 42 | } 43 | 44 | public DynamicMessage buildSymEncryption() { 45 | SymEncryption symEncryption = new SymEncryption(); 46 | symEncryption.setSymEncryptionMethod(SYM_ENCRYPTION); 47 | 48 | return DynamicMessage.createMsgOfEncode(symEncryption); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/DynamicSerializerFactory.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.codec.serialize.body.*; 5 | import org.lwl.netty.dynamic.message.Body; 6 | 7 | import java.util.EnumMap; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/7/29 12 | * @description 13 | */ 14 | 15 | 16 | public final class DynamicSerializerFactory { 17 | 18 | private DynamicSerializerFactory() { 19 | throw new IllegalAccessError("can not use constructor."); 20 | } 21 | 22 | private static EnumMap> bodySerializerMap = new EnumMap<>(DynamicMsgType.class); 23 | 24 | static { 25 | bodySerializerMap.put(DynamicMsgType.UNKNOWN, DefaultBodySerializer.getInstance()); 26 | bodySerializerMap.put(DynamicMsgType.SSL, SslBodySerializer.getInstance()); 27 | bodySerializerMap.put(DynamicMsgType.SYM_ENCRYPTION, SymEncryptionSerializer.getInstance()); 28 | bodySerializerMap.put(DynamicMsgType.RANDOM_CODE, RandomCodeBodySerializer.getInstance()); 29 | bodySerializerMap.put(DynamicMsgType.LOGIN_REQ, LoginReqBodySerializer.getInstance()); 30 | bodySerializerMap.put(DynamicMsgType.LOGIN_RESP, LoginRespBodySerializer.getInstance()); 31 | bodySerializerMap.put(DynamicMsgType.LOGOUT, LogoutBodySerializer.getInstance()); 32 | bodySerializerMap.put(DynamicMsgType.HEARTBEAT_REQ, HtReqBodySerializer.getInstance()); 33 | bodySerializerMap.put(DynamicMsgType.HEARTBEAT_RESP, HtRespBodySerializer.getInstance()); 34 | } 35 | 36 | public static IBodySerializer getBodySerializer(final DynamicMsgType msgType) { 37 | IBodySerializer bodySerializer = bodySerializerMap.get(msgType); 38 | 39 | return null != bodySerializer ? bodySerializer: DefaultBodySerializer.getInstance(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/HeaderSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.core.Decoder; 5 | import org.lwl.netty.core.Encoder; 6 | import org.lwl.netty.dynamic.DynamicMsgType; 7 | import org.lwl.netty.dynamic.message.Header; 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/7/29 11 | * @description 12 | */ 13 | 14 | public class HeaderSerializer { 15 | private static final HeaderSerializer INSTANCE = new HeaderSerializer(); 16 | private HeaderSerializer(){} 17 | 18 | public static HeaderSerializer getInstance() { 19 | return INSTANCE; 20 | } 21 | 22 | public void serialize(ByteBuf outByteBuf, Header header) throws Exception { 23 | Encoder.writeLong(outByteBuf, header.getMsgNum()); 24 | Encoder.writeByte(outByteBuf, header.getMsgType().getMsgType()); 25 | Encoder.writeString(outByteBuf, header.getMsgTime()); 26 | } 27 | 28 | public Header deserialize(ByteBuf inByteBuf) throws Exception { 29 | long msgNum = Decoder.readLong(inByteBuf); 30 | Byte msgType = Decoder.readByte(inByteBuf); 31 | String msgTime = Decoder.readString(inByteBuf); 32 | 33 | Header header = new Header(); 34 | header.setMsgNum(msgNum); 35 | header.setMsgType(DynamicMsgType.getMsgTypeEnum(msgType)); 36 | header.setMsgTime(msgTime); 37 | 38 | return header; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/IBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/7/29 9 | * @description 10 | */ 11 | 12 | 13 | public interface IBodySerializer { 14 | public void serialize(ByteBuf outByteBuf, Body body) throws Exception; 15 | 16 | public T deserialize(ByteBuf inByteBuf) throws Exception; 17 | } 18 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/TailSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.core.CommonUtil; 5 | import org.lwl.netty.core.Decoder; 6 | import org.lwl.netty.core.Encoder; 7 | import org.lwl.netty.dynamic.message.Tail; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/7/29 12 | * @description 13 | */ 14 | 15 | 16 | public class TailSerializer { 17 | private static final TailSerializer INSTANCE = new TailSerializer(); 18 | private TailSerializer(){} 19 | 20 | public static TailSerializer getInstance() { 21 | return INSTANCE; 22 | } 23 | 24 | public void serialize(ByteBuf outByteBuf, Tail msg) throws Exception { 25 | int checkSum = CommonUtil.calCheckSum(outByteBuf, outByteBuf.writerIndex()); 26 | Encoder.writeInt(outByteBuf, checkSum); 27 | } 28 | 29 | public Tail deserialize(ByteBuf inByteBuf) throws Exception { 30 | int checkSum = Decoder.readInt(inByteBuf); 31 | 32 | Tail tail = new Tail(); 33 | tail.setCheckSum(checkSum); 34 | 35 | return tail; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/DefaultBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 5 | import org.lwl.netty.dynamic.message.Body; 6 | 7 | /** 8 | * @author thinking_fioa 9 | * @createTime 2018/7/29 10 | * @description 11 | */ 12 | 13 | 14 | public final class DefaultBodySerializer implements IBodySerializer { 15 | private static final DefaultBodySerializer INSTANCE = new DefaultBodySerializer(); 16 | private DefaultBodySerializer(){} 17 | 18 | public static DefaultBodySerializer getInstance() { 19 | return INSTANCE; 20 | } 21 | 22 | @Override 23 | public void serialize(ByteBuf outByteBuf, Body body) { 24 | } 25 | 26 | @Override 27 | public Body deserialize(ByteBuf inByteBuf) { 28 | return new Body(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/HtReqBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 5 | import org.lwl.netty.dynamic.message.Body; 6 | import org.lwl.netty.dynamic.message.body.HeartbeatReqBody; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/7/29 11 | * @description 12 | */ 13 | 14 | 15 | public final class HtReqBodySerializer implements IBodySerializer { 16 | 17 | private static final HtReqBodySerializer INSTANCE = new HtReqBodySerializer(); 18 | private HtReqBodySerializer(){} 19 | 20 | public static HtReqBodySerializer getInstance() { 21 | return INSTANCE; 22 | } 23 | 24 | @Override 25 | public void serialize(ByteBuf outByteBuf, Body body) { 26 | 27 | } 28 | 29 | @Override 30 | public HeartbeatReqBody deserialize(ByteBuf inByteBuf) { 31 | return new HeartbeatReqBody(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/HtRespBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 5 | import org.lwl.netty.dynamic.message.Body; 6 | import org.lwl.netty.dynamic.message.body.HeartbeatRespBody; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/7/29 11 | * @description 12 | */ 13 | 14 | 15 | public final class HtRespBodySerializer implements IBodySerializer { 16 | 17 | private static final HtRespBodySerializer INSTANCE = new HtRespBodySerializer(); 18 | private HtRespBodySerializer(){} 19 | 20 | public static HtRespBodySerializer getInstance() { 21 | return INSTANCE; 22 | } 23 | 24 | @Override 25 | public void serialize(ByteBuf outByteBuf, Body body) { 26 | 27 | } 28 | 29 | @Override 30 | public HeartbeatRespBody deserialize(ByteBuf inByteBuf) { 31 | return new HeartbeatRespBody(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/LoginReqBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.core.Decoder; 5 | import org.lwl.netty.core.Encoder; 6 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 7 | import org.lwl.netty.dynamic.message.Body; 8 | import org.lwl.netty.dynamic.message.body.HeartbeatRespBody; 9 | import org.lwl.netty.dynamic.message.body.LoginReqBody; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/7/29 14 | * @description 15 | */ 16 | 17 | 18 | public final class LoginReqBodySerializer implements IBodySerializer { 19 | private static final LoginReqBodySerializer INSTANCE = new LoginReqBodySerializer(); 20 | private LoginReqBodySerializer(){} 21 | 22 | public static LoginReqBodySerializer getInstance() { 23 | return INSTANCE; 24 | } 25 | 26 | @Override 27 | public void serialize(ByteBuf outByteBuf, Body body) { 28 | LoginReqBody login = (LoginReqBody)body; 29 | Encoder.writeString(outByteBuf, login.getUserName()); 30 | Encoder.writeString(outByteBuf, login.getPassword()); 31 | } 32 | 33 | @Override 34 | public LoginReqBody deserialize(ByteBuf inByteBuf) { 35 | String userName = Decoder.readString(inByteBuf); 36 | String password = Decoder.readString(inByteBuf); 37 | 38 | LoginReqBody loginReqBody = new LoginReqBody(); 39 | loginReqBody.setUserName(userName); 40 | loginReqBody.setPassword(password); 41 | 42 | return loginReqBody; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/LoginRespBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 5 | import org.lwl.netty.dynamic.message.Body; 6 | import org.lwl.netty.dynamic.message.body.LoginRespBody; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/7/29 11 | * @description 12 | */ 13 | 14 | 15 | public final class LoginRespBodySerializer implements IBodySerializer { 16 | private static final LoginRespBodySerializer INSTANCE = new LoginRespBodySerializer(); 17 | private LoginRespBodySerializer(){} 18 | 19 | public static LoginRespBodySerializer getInstance() { 20 | return INSTANCE; 21 | } 22 | 23 | @Override 24 | public void serialize(ByteBuf outByteBuf, Body body) { 25 | 26 | } 27 | 28 | @Override 29 | public LoginRespBody deserialize(ByteBuf inByteBuf) { 30 | return new LoginRespBody(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/LogoutBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 5 | import org.lwl.netty.dynamic.message.Body; 6 | import org.lwl.netty.dynamic.message.body.LogoutBody; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/7/29 11 | * @description 12 | */ 13 | 14 | 15 | public class LogoutBodySerializer implements IBodySerializer { 16 | 17 | private static final LogoutBodySerializer INSTANCE = new LogoutBodySerializer(); 18 | private LogoutBodySerializer(){} 19 | 20 | public static LogoutBodySerializer getInstance() { 21 | return INSTANCE; 22 | } 23 | 24 | 25 | @Override 26 | public void serialize(ByteBuf outByteBuf, Body body) { 27 | 28 | } 29 | 30 | @Override 31 | public LogoutBody deserialize(ByteBuf inByteBuf) { 32 | return new LogoutBody(); 33 | } 34 | } -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/RandomCodeBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.core.Decoder; 5 | import org.lwl.netty.core.Encoder; 6 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 7 | import org.lwl.netty.dynamic.message.Body; 8 | import org.lwl.netty.dynamic.message.body.RandomCodeBody; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/7/29 13 | * @description 14 | */ 15 | 16 | 17 | public final class RandomCodeBodySerializer implements IBodySerializer { 18 | private static final RandomCodeBodySerializer INSTANCE = new RandomCodeBodySerializer(); 19 | private RandomCodeBodySerializer(){} 20 | 21 | public static RandomCodeBodySerializer getInstance() { 22 | return INSTANCE; 23 | } 24 | 25 | @Override 26 | public void serialize(ByteBuf outByteBuf, Body body) { 27 | RandomCodeBody randomCodeBody = (RandomCodeBody)body; 28 | Encoder.writeString(outByteBuf, randomCodeBody.getRandomCode()); 29 | } 30 | 31 | @Override 32 | public RandomCodeBody deserialize(ByteBuf inByteBuf) { 33 | String randomCode = Decoder.readString(inByteBuf); 34 | 35 | RandomCodeBody randomCodeBody = new RandomCodeBody(); 36 | randomCodeBody.setRandomCode(randomCode); 37 | 38 | return randomCodeBody; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/SslBodySerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.core.Decoder; 5 | import org.lwl.netty.core.Encoder; 6 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 7 | import org.lwl.netty.dynamic.message.Body; 8 | import org.lwl.netty.dynamic.message.body.RandomCodeBody; 9 | import org.lwl.netty.dynamic.message.body.SslBody; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/7/29 14 | * @description 15 | */ 16 | 17 | 18 | public final class SslBodySerializer implements IBodySerializer { 19 | private static final SslBodySerializer INSTANCE = new SslBodySerializer(); 20 | private SslBodySerializer(){} 21 | 22 | public static SslBodySerializer getInstance() { 23 | return INSTANCE; 24 | } 25 | 26 | @Override 27 | public void serialize(ByteBuf outByteBuf, Body body) { 28 | SslBody sslBody = (SslBody)body; 29 | Encoder.writeString(outByteBuf, sslBody.getSslVersion()); 30 | } 31 | 32 | @Override 33 | public SslBody deserialize(ByteBuf inByteBuf) { 34 | String sslVersion = Decoder.readString(inByteBuf); 35 | 36 | SslBody sslBody = new SslBody(); 37 | sslBody.setSslVersion(sslVersion); 38 | 39 | return sslBody; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/codec/serialize/body/SymEncryptionSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.codec.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import org.lwl.netty.core.Decoder; 5 | import org.lwl.netty.core.Encoder; 6 | import org.lwl.netty.dynamic.codec.serialize.IBodySerializer; 7 | import org.lwl.netty.dynamic.message.Body; 8 | import org.lwl.netty.dynamic.message.body.SymEncryption; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/7/29 13 | * @description 14 | */ 15 | 16 | 17 | public class SymEncryptionSerializer implements IBodySerializer { 18 | private static final SymEncryptionSerializer INSTANCE = new SymEncryptionSerializer(); 19 | 20 | private SymEncryptionSerializer() { 21 | } 22 | 23 | public static SymEncryptionSerializer getInstance() { 24 | return INSTANCE; 25 | } 26 | 27 | @Override 28 | public void serialize(ByteBuf outByteBuf, Body body) { 29 | SymEncryption SymEncryption = (SymEncryption) body; 30 | Encoder.writeString(outByteBuf, SymEncryption.getSymEncryptionMethod()); 31 | } 32 | 33 | @Override 34 | public SymEncryption deserialize(ByteBuf inByteBuf) { 35 | String symEncryptionMethod = Decoder.readString(inByteBuf); 36 | 37 | SymEncryption symEncryption = new SymEncryption(); 38 | symEncryption.setSymEncryptionMethod(symEncryptionMethod); 39 | 40 | return symEncryption; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/Body.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message; 2 | 3 | 4 | import org.lwl.netty.dynamic.DynamicMsgType; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/9 9 | * @description 10 | */ 11 | 12 | 13 | public class Body { 14 | 15 | public DynamicMsgType msgType() { 16 | return DynamicMsgType.UNKNOWN; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/DynamicMessage.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/4/21 6 | * @description 自定义消息格式消息 7 | */ 8 | 9 | 10 | public class DynamicMessage { 11 | 12 | private Header header; 13 | 14 | private Body body; 15 | 16 | private Tail tail; 17 | 18 | private DynamicMessage(Header header, Body body, Tail tail) { 19 | this.header = header; 20 | this.body = body; 21 | this.tail = tail; 22 | } 23 | 24 | private DynamicMessage(Body body) { 25 | this.header = new Header(); 26 | this.body = body; 27 | this.tail = new Tail(); 28 | } 29 | 30 | public static DynamicMessage createMsgOfEncode(Body body) { 31 | return new DynamicMessage(body); 32 | } 33 | 34 | public static DynamicMessage createMsgOfDecode(Header header, Body body, Tail tail) { 35 | return new DynamicMessage(header, body, tail); 36 | } 37 | 38 | public Header getHeader() { 39 | return header; 40 | } 41 | 42 | public void setHeader(Header header) { 43 | this.header = header; 44 | } 45 | 46 | public Body getBody() { 47 | return body; 48 | } 49 | 50 | public void setBody(Body body) { 51 | this.body = body; 52 | } 53 | 54 | public Tail getTail() { 55 | return tail; 56 | } 57 | 58 | public void setTail(Tail tail) { 59 | this.tail = tail; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | return "DynamicMessage: " + header.toString() + body.toString() + tail.toString(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/Header.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/4/21 11 | * @description 消息头 12 | */ 13 | 14 | 15 | public class Header { 16 | /** 17 | * 发送消息数目 18 | */ 19 | private long msgNum; 20 | 21 | /** 22 | * 消息类型,{@code DynamicMsgType} 23 | */ 24 | private DynamicMsgType msgType; 25 | 26 | /** 27 | * 消息时间,格式: 28 | */ 29 | private String msgTime; 30 | 31 | public long getMsgNum() { 32 | return msgNum; 33 | } 34 | 35 | public void setMsgNum(long msgNum) { 36 | this.msgNum = msgNum; 37 | } 38 | 39 | public DynamicMsgType getMsgType() { 40 | return msgType; 41 | } 42 | 43 | public void setMsgType(DynamicMsgType msgType) { 44 | this.msgType = msgType; 45 | } 46 | 47 | public String getMsgTime() { 48 | return msgTime; 49 | } 50 | 51 | public void setMsgTime(String msgTime) { 52 | this.msgTime = msgTime; 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | StringBuilder sb = new StringBuilder(); 58 | sb.append("Header ["); 59 | sb.append("msgNum=").append(msgNum); 60 | sb.append(", msgType=").append(msgType).append("]"); 61 | 62 | return sb.toString(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/Tail.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/4/21 6 | * @description 消息体尾部 7 | */ 8 | 9 | 10 | public class Tail { 11 | 12 | private int checkSum; 13 | 14 | public int getCheckSum() { 15 | return checkSum; 16 | } 17 | 18 | public void setCheckSum(int checkSum) { 19 | this.checkSum = checkSum; 20 | } 21 | 22 | /** 23 | * 属性字节数 24 | * @return 25 | */ 26 | public static int byteSize() { 27 | return 4; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | StringBuilder sb = new StringBuilder(); 33 | sb.append("Tail ["); 34 | sb.append("checkSum=").append(checkSum).append("]"); 35 | 36 | return sb.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/HeartbeatReqBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/26 9 | * @description 心跳数据 10 | */ 11 | 12 | 13 | public class HeartbeatReqBody extends Body { 14 | // nothing 15 | 16 | @Override 17 | public DynamicMsgType msgType() { 18 | return DynamicMsgType.HEARTBEAT_REQ; 19 | } 20 | 21 | @Override 22 | public String toString(){ 23 | 24 | return "HeartbeatReqBody []"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/HeartbeatRespBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/26 9 | * @description 心跳数据 10 | */ 11 | 12 | 13 | public class HeartbeatRespBody extends Body { 14 | // nothing 15 | 16 | @Override 17 | public DynamicMsgType msgType() { 18 | return DynamicMsgType.HEARTBEAT_RESP; 19 | } 20 | 21 | @Override 22 | public String toString(){ 23 | 24 | return "HeartbeatRespBody []"; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/LoginReqBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/9 9 | * @description 登陆消息 10 | */ 11 | 12 | 13 | public class LoginReqBody extends Body { 14 | 15 | private String userName; 16 | private String password; 17 | 18 | public String getUserName() { 19 | return userName; 20 | } 21 | 22 | public void setUserName(String userName) { 23 | this.userName = userName; 24 | } 25 | 26 | public String getPassword() { 27 | return password; 28 | } 29 | 30 | public void setPassword(String password) { 31 | this.password = password; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | StringBuilder sb = new StringBuilder(); 37 | sb.append("LoginReqBody ["); 38 | sb.append("userName=").append(userName); 39 | sb.append(", password=").append(password).append("]"); 40 | 41 | return sb.toString(); 42 | } 43 | 44 | @Override 45 | public DynamicMsgType msgType() { 46 | return DynamicMsgType.LOGIN_REQ; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/LoginRespBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/9 9 | * @description 登陆消息 10 | */ 11 | 12 | 13 | public class LoginRespBody extends Body { 14 | 15 | @Override 16 | public String toString() { 17 | StringBuilder sb = new StringBuilder(); 18 | sb.append("LoginRespBody []"); 19 | return sb.toString(); 20 | } 21 | 22 | @Override 23 | public DynamicMsgType msgType() { 24 | return DynamicMsgType.LOGIN_RESP; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/LogoutBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/7/29 9 | * @description 10 | */ 11 | 12 | 13 | public class LogoutBody extends Body { 14 | @Override 15 | public DynamicMsgType msgType() { 16 | return DynamicMsgType.LOGOUT; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | StringBuilder sb = new StringBuilder(); 22 | sb.append("LogoutBody []"); 23 | return sb.toString(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/RandomCodeBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/7/28 9 | * @description 10 | */ 11 | 12 | 13 | public class RandomCodeBody extends Body{ 14 | 15 | private String randomCode; 16 | 17 | public String getRandomCode() { 18 | return randomCode; 19 | } 20 | 21 | public void setRandomCode(String randomCode) { 22 | this.randomCode = randomCode; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | StringBuilder sb = new StringBuilder(); 28 | sb.append("RandomCodeBody ["); 29 | sb.append("randomCode=").append(randomCode).append("]"); 30 | 31 | return sb.toString(); 32 | } 33 | 34 | @Override 35 | public DynamicMsgType msgType() { 36 | return DynamicMsgType.RANDOM_CODE; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/SslBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/7/28 9 | * @description 10 | */ 11 | 12 | 13 | public class SslBody extends Body { 14 | 15 | /** 16 | * ssl的版本 17 | */ 18 | private String sslVersion; 19 | 20 | public String getSslVersion() { 21 | return sslVersion; 22 | } 23 | 24 | public void setSslVersion(String sslVersion) { 25 | this.sslVersion = sslVersion; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | StringBuilder sb = new StringBuilder(); 31 | sb.append("SslBody ["); 32 | sb.append("sslVersion=").append(sslVersion).append("]"); 33 | 34 | return sb.toString(); 35 | } 36 | 37 | @Override 38 | public DynamicMsgType msgType() { 39 | return DynamicMsgType.SSL; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/message/body/SymEncryption.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.message.body; 2 | 3 | import org.lwl.netty.dynamic.DynamicMsgType; 4 | import org.lwl.netty.dynamic.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/7/28 9 | * @description 10 | */ 11 | 12 | 13 | public class SymEncryption extends Body{ 14 | /** 15 | * 对称加密方法 16 | */ 17 | private String symEncryptionMethod; 18 | 19 | public String getSymEncryptionMethod() { 20 | return symEncryptionMethod; 21 | } 22 | 23 | public void setSymEncryptionMethod(String symEncryptionMethod) { 24 | this.symEncryptionMethod = symEncryptionMethod; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | StringBuilder sb = new StringBuilder(); 30 | sb.append("SymEncryption ["); 31 | sb.append("symEncryptionMethod=").append(symEncryptionMethod).append("]"); 32 | 33 | return sb.toString(); 34 | } 35 | 36 | @Override 37 | public DynamicMsgType msgType() { 38 | return DynamicMsgType.SYM_ENCRYPTION; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/server/handler/ExceptionHanlder.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.server.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/8/12 11 | * @description 12 | */ 13 | 14 | 15 | public class ExceptionHanlder extends ChannelInboundHandlerAdapter{ 16 | private static final Logger LOGGER = LogManager.getLogger(ExceptionHanlder.class); 17 | 18 | @Override 19 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 20 | throws Exception { 21 | LOGGER.error("happen unknown exception.", cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/server/handler/HeartbeatServerHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.server.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import io.netty.handler.timeout.IdleState; 6 | import io.netty.handler.timeout.IdleStateEvent; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | import org.lwl.netty.dynamic.DynamicConfig; 10 | import org.lwl.netty.dynamic.DynamicMsgType; 11 | import org.lwl.netty.dynamic.message.DynamicMessage; 12 | import org.lwl.netty.dynamic.message.body.HeartbeatReqBody; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/8/12 17 | * @description 18 | */ 19 | 20 | 21 | public class HeartbeatServerHandler extends ChannelInboundHandlerAdapter{ 22 | private static final Logger LOGGER = LogManager.getLogger(HeartbeatServerHandler.class); 23 | private int lossConnectTime = 0; 24 | 25 | @Override 26 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 27 | if(evt instanceof IdleStateEvent) { 28 | IdleStateEvent event = (IdleStateEvent)evt; 29 | if(event.state() == IdleState.READER_IDLE) { 30 | lossConnectTime ++; 31 | if(lossConnectTime > DynamicConfig.getHtMultiple()) { 32 | LOGGER.error("heartbeat timeout. close channel {}", ctx.channel().remoteAddress()); 33 | ctx.close(); 34 | return; 35 | } 36 | } else if(event.state() == IdleState.WRITER_IDLE) { 37 | LOGGER.warn("heartbeat timeout. lossCount {}", lossConnectTime); 38 | ctx.writeAndFlush(buildHtReqMsg()); 39 | } 40 | } else { 41 | ctx.fireUserEventTriggered(evt); 42 | } 43 | } 44 | 45 | @Override 46 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 47 | DynamicMessage message = (DynamicMessage) msg; 48 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 49 | lossConnectTime = 0; 50 | if(DynamicMsgType.HEARTBEAT_RESP.equals(msgType)) { 51 | LOGGER.debug("receive heartbeat resp"); 52 | return; 53 | } else { 54 | ctx.fireChannelRead(msg); 55 | } 56 | } 57 | 58 | private DynamicMessage buildHtReqMsg() { 59 | HeartbeatReqBody htReqBody = new HeartbeatReqBody(); 60 | 61 | return DynamicMessage.createMsgOfEncode(htReqBody); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/server/handler/LoginRespHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.server.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.DynamicConfig; 8 | import org.lwl.netty.dynamic.DynamicMsgType; 9 | import org.lwl.netty.dynamic.message.DynamicMessage; 10 | import org.lwl.netty.dynamic.message.body.LoginReqBody; 11 | import org.lwl.netty.dynamic.message.body.LoginRespBody; 12 | 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/8/12 17 | * @description 18 | */ 19 | 20 | 21 | public class LoginRespHandler extends ChannelInboundHandlerAdapter { 22 | private static final Logger LOGGER = LogManager.getLogger(LoginRespHandler.class); 23 | 24 | private final String USERNAME = DynamicConfig.getUserName(); 25 | private final String PASSWD = DynamicConfig.getPasswd(); 26 | 27 | @Override 28 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 29 | DynamicMessage message = (DynamicMessage) msg; 30 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 31 | if(DynamicMsgType.LOGIN_REQ.equals(msgType)) { 32 | LOGGER.info("receive login req."); 33 | LoginReqBody reqBody = (LoginReqBody)message.getBody(); 34 | if(checkPermission(reqBody)) { 35 | LOGGER.info("user check pass. login resp sent."); 36 | ctx.channel().writeAndFlush(buildLoginResp()); 37 | } 38 | } else { 39 | ctx.fireChannelRead(msg); 40 | } 41 | } 42 | 43 | private boolean checkPermission(LoginReqBody reqBody) { 44 | final String userName = reqBody.getUserName(); 45 | final String passwd = reqBody.getPassword(); 46 | 47 | return USERNAME.equals(userName) && PASSWD.equals(passwd); 48 | } 49 | 50 | private DynamicMessage buildLoginResp() { 51 | LoginRespBody respBody = new LoginRespBody(); 52 | 53 | return DynamicMessage.createMsgOfEncode(respBody); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/server/handler/RandomCodeServerHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.server.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.DynamicMsgType; 8 | import org.lwl.netty.dynamic.message.DynamicMessage; 9 | import org.lwl.netty.dynamic.message.body.RandomCodeBody; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/8/13 14 | * @description 15 | */ 16 | 17 | 18 | public class RandomCodeServerHandler extends ChannelInboundHandlerAdapter { 19 | private static final Logger LOGGER = LogManager.getLogger(RandomCodeServerHandler.class); 20 | 21 | @Override 22 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 23 | DynamicMessage message = (DynamicMessage) msg; 24 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 25 | if(DynamicMsgType.RANDOM_CODE.equals(msgType)) { 26 | LOGGER.info("receive randomCode req. accomplish ssl process"); 27 | RandomCodeBody randomCodeBody = (RandomCodeBody)message.getBody(); 28 | ctx.channel().writeAndFlush(buildSslBody(randomCodeBody.getRandomCode())); 29 | } else { 30 | ctx.fireChannelRead(msg); 31 | } 32 | } 33 | 34 | private DynamicMessage buildSslBody(String randomCode) { 35 | RandomCodeBody randomCodeBody = new RandomCodeBody(); 36 | randomCodeBody.setRandomCode(randomCode); 37 | 38 | return DynamicMessage.createMsgOfEncode(randomCodeBody); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/server/handler/SslServerHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.server.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.DynamicMsgType; 8 | import org.lwl.netty.dynamic.message.DynamicMessage; 9 | import org.lwl.netty.dynamic.message.body.SslBody; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/8/12 14 | * @description 15 | */ 16 | 17 | 18 | public class SslServerHandler extends ChannelInboundHandlerAdapter { 19 | private static final Logger LOGGER = LogManager.getLogger(SslServerHandler.class); 20 | 21 | @Override 22 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 23 | DynamicMessage message = (DynamicMessage) msg; 24 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 25 | if(DynamicMsgType.SSL.equals(msgType)) { 26 | LOGGER.info("receive ssl req."); 27 | SslBody sslBody = (SslBody)message.getBody(); 28 | ctx.channel().writeAndFlush(buildSslBody(sslBody.getSslVersion())); 29 | } else { 30 | ctx.fireChannelRead(msg); 31 | } 32 | } 33 | 34 | private DynamicMessage buildSslBody(String version) { 35 | SslBody sslBody = new SslBody(); 36 | sslBody.setSslVersion(version); 37 | 38 | return DynamicMessage.createMsgOfEncode(sslBody); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/dynamic/server/handler/SymEncryptionServerHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.dynamic.server.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.dynamic.DynamicMsgType; 8 | import org.lwl.netty.dynamic.message.DynamicMessage; 9 | import org.lwl.netty.dynamic.message.body.SymEncryption; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/8/12 14 | * @description 15 | */ 16 | 17 | 18 | public class SymEncryptionServerHandler extends ChannelInboundHandlerAdapter { 19 | private static final Logger LOGGER = LogManager.getLogger(SymEncryptionServerHandler.class); 20 | 21 | @Override 22 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 23 | DynamicMessage message = (DynamicMessage) msg; 24 | final DynamicMsgType msgType = message.getHeader().getMsgType(); 25 | if(DynamicMsgType.SYM_ENCRYPTION.equals(msgType)) { 26 | LOGGER.info("receive symEncryption req."); 27 | SymEncryption symBody = (SymEncryption)message.getBody(); 28 | ctx.channel().writeAndFlush(buildSslBody(symBody.getSymEncryptionMethod())); 29 | } else { 30 | ctx.fireChannelRead(msg); 31 | } 32 | } 33 | 34 | private DynamicMessage buildSslBody(String symEncryptionMethod) { 35 | SymEncryption symBody = new SymEncryption(); 36 | symBody.setSymEncryptionMethod(symEncryptionMethod); 37 | 38 | return DynamicMessage.createMsgOfEncode(symBody); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/udp/Test.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.udp; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/7/22 6 | * @description 7 | */ 8 | 9 | 10 | public class Test { 11 | } 12 | -------------------------------------------------------------------------------- /netty-practice/src/main/java/org/lwl/netty/util/Test.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.util; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/7/28 6 | * @description 7 | */ 8 | 9 | 10 | public class Test { 11 | } 12 | -------------------------------------------------------------------------------- /netty-private-protocol/docs/pics/lengthField/lengthField-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/docs/pics/lengthField/lengthField-1.png -------------------------------------------------------------------------------- /netty-private-protocol/docs/pics/lengthField/lengthField-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/docs/pics/lengthField/lengthField-2.png -------------------------------------------------------------------------------- /netty-private-protocol/docs/pics/lengthField/lengthField-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/docs/pics/lengthField/lengthField-3.png -------------------------------------------------------------------------------- /netty-private-protocol/docs/pics/lengthField/lengthField-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/docs/pics/lengthField/lengthField-4.png -------------------------------------------------------------------------------- /netty-private-protocol/docs/pics/lengthField/lengthField-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/docs/pics/lengthField/lengthField-5.png -------------------------------------------------------------------------------- /netty-private-protocol/docs/pics/lengthField/lengthField-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/docs/pics/lengthField/lengthField-6.png -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/bin/buildProto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | protoc -I=../proto/ --java_out=../../java/ Body.proto 4 | protoc -I=../proto/ --java_out=../../java/ Header.proto 5 | protoc -I=../proto/ --java_out=../../java/ HeartbeatReqBody.proto 6 | protoc -I=../proto/ --java_out=../../java/ HeartbeatRespBody.proto 7 | protoc -I=../proto/ --java_out=../../java/ LoginReqBody.proto 8 | protoc -I=../proto/ --java_out=../../java/ LoginRespBody.proto 9 | protoc -I=../proto/ --java_out=../../java/ LogoutBody.proto 10 | protoc -I=../proto/ --java_out=../../java/ ProtocolDataBody.proto 11 | protoc -I=../proto/ --java_out=../../java/ ProtocolSubBody.proto 12 | protoc -I=../proto/ --java_out=../../java/ Tail.proto 13 | protoc -I=../proto/ --java_out=../../java/ ProtocolMessage.proto -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/data/entertainment.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/src/main/Resources/data/entertainment.txt -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/data/news.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/src/main/Resources/data/news.txt -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/data/sports.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-private-protocol/src/main/Resources/data/sports.txt -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/netty-private-protocol.properties: -------------------------------------------------------------------------------- 1 | 2 | ## netty server port 3 | ip=127.0.0.1 4 | port=9080 5 | 6 | ## unit: s 7 | heartbeat.interval=5 8 | 9 | ## login user/passwd 10 | username=thinkingfioa 11 | password=123456 12 | 13 | ### UTF-8/GBK 14 | charset.format=UTF-8 15 | 16 | ### transport pkg max size, unit: B 17 | pkg.max.len=4096 18 | 19 | ### codec. 1 - Marshalling; 2 - Kryo; 3 - Protobuf; 4 - Thrift; 5 - Avro 20 | message.codec=2 -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/Body.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "Body"; 5 | 6 | message BodyP { 7 | 8 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/Header.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "Header"; 5 | 6 | message HeaderP { 7 | int64 msgNum=1; 8 | 9 | MessageTypeEnum msgType=2; 10 | 11 | string msgTime=3; 12 | 13 | int32 flag = 4; 14 | 15 | int32 oneByte = 5; 16 | 17 | map attachment=6; 18 | } 19 | 20 | enum MessageTypeEnum { 21 | UNKNOWN=0; 22 | LOGIN_REQ=1; 23 | LOGIN_RESP=2; 24 | LOGOUT=3; 25 | HEARTBEAT_REQ=4; 26 | HEARTBEAT_RESP=5; 27 | PROTOCOL_SUB=6; 28 | PROTOCOL_DATA=7; 29 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/HeartbeatReqBody.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "HeartbeatReqBody"; 5 | 6 | message HeartbeatReqBodyP { 7 | 8 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/HeartbeatRespBody.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "HeartbeatRespBody"; 5 | 6 | message HeartbeatRespBodyP { 7 | 8 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/LoginReqBody.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "LoginReqBody"; 5 | 6 | message LoginReqBodyP { 7 | string userName = 1; 8 | string password = 2; 9 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/LoginRespBody.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "LoginRespBody"; 5 | 6 | message LoginRespBodyP { 7 | 8 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/LogoutBody.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "LogoutBody"; 5 | 6 | message LogoutBodyP { 7 | 8 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/ProtocolDataBody.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "ProtocolDataBody"; 5 | 6 | message ProtocolDataBodyP { 7 | sint64 pkgSum = 1; 8 | sint64 pkgSequenceNum = 2; 9 | int32 contentLen = 3; 10 | bytes content = 4; 11 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/ProtocolMessage.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "ProtocolMessage"; 5 | 6 | import "Header.proto"; 7 | import "Body.proto"; 8 | import "HeartbeatReqBody.proto"; 9 | import "HeartbeatRespBody.proto"; 10 | import "LoginReqBody.proto"; 11 | import "LoginRespBody.proto"; 12 | import "LogoutBody.proto"; 13 | import "ProtocolDataBody.proto"; 14 | import "ProtocolSubBody.proto"; 15 | import "Tail.proto"; 16 | 17 | message ProtocolMessageP { 18 | HeaderP header = 1; 19 | oneof body { 20 | BodyP bodyMsg = 2; 21 | HeartbeatReqBodyP heartbeatReqBody = 3; 22 | HeartbeatRespBodyP heartbeatRespBody = 4; 23 | LoginReqBodyP loginReqBody = 5; 24 | LoginRespBodyP loginRespBody = 6; 25 | LogoutBodyP logoutBody = 7; 26 | ProtocolDataBodyP protocolDataBody = 8; 27 | ProtocolSubBodyP protocolSubBody = 9; 28 | } 29 | TailP tail = 10; 30 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/ProtocolSubBody.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "ProtocolSubBody"; 5 | 6 | message ProtocolSubBodyP { 7 | repeated ProtocolDataType dataTypeList = 1; 8 | } 9 | 10 | enum ProtocolDataType { 11 | DEFAULT = 0; 12 | NEWS = 1; 13 | SPORTS = 2; 14 | ENTERTAINMENT = 3; 15 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/Resources/proto/Tail.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.lwl.netty.message.protobuf"; 4 | option java_outer_classname = "Tail"; 5 | 6 | message TailP { 7 | int32 checkSum=1; 8 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/NettyServerAndClientStart.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty; 2 | 3 | import org.lwl.netty.client.NettyClient; 4 | import org.lwl.netty.client.NettyClientAdapter; 5 | import org.lwl.netty.config.ProtocolConfig; 6 | import org.lwl.netty.server.NettyServer; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/4/22 13 | * @description 分别以线程的方式启动NettyClient和NettyServer 14 | */ 15 | 16 | 17 | public class NettyServerAndClientStart { 18 | 19 | public static void main(String [] args) throws IOException, InterruptedException { 20 | ProtocolConfig.init(); 21 | // 用线程启动 22 | // 启动 Server 23 | new Thread(() -> { 24 | new NettyServer().start(); 25 | }).start(); 26 | 27 | Thread.sleep(60000); 28 | 29 | new Thread(() -> { 30 | new NettyClientAdapter(new NettyClient()).start(); 31 | }).start(); 32 | } 33 | } -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/ProtobufServerAndClientStart.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty; 2 | 3 | import org.lwl.netty.client.NettyClientAdapter; 4 | import org.lwl.netty.client.ProtobufNettyClient; 5 | import org.lwl.netty.config.ProtocolConfig; 6 | import org.lwl.netty.server.NettyServer; 7 | import org.lwl.netty.server.ProtobufNettyServer; 8 | 9 | import java.io.IOException; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/7/8 14 | * @description 由于Protobuf使用的消息{@link org.lwl.netty.message.protobuf}非常特殊,所以,所有的传输机制 15 | * 都与编码方式:Marshalling和Kryo不同。单独一套。 16 | */ 17 | 18 | public class ProtobufServerAndClientStart { 19 | public static void main(String [] args) throws IOException { 20 | ProtocolConfig.init(); 21 | new Thread(() -> { 22 | new ProtobufNettyServer().start(); 23 | }).start(); 24 | 25 | new Thread(() -> { 26 | new NettyClientAdapter(new ProtobufNettyClient()).start(); 27 | }).start(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/client/NettyClientAdapter.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.client; 2 | 3 | import io.netty.channel.ChannelFuture; 4 | import io.netty.channel.ChannelFutureListener; 5 | import io.netty.channel.EventLoopGroup; 6 | import io.netty.channel.nio.NioEventLoopGroup; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | import org.lwl.netty.config.ProtocolConfig; 10 | import org.lwl.netty.server.NettyServer; 11 | import org.lwl.netty.util.concurrent.CustomThreadFactory; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/5/12 16 | * @description NettyClient适配器,可以控制重连机制。另一个项目可以见到链路切换 17 | */ 18 | 19 | public class NettyClientAdapter { 20 | private static final Logger LOGGER = LogManager.getLogger(NettyClientAdapter.class); 21 | 22 | private static final CustomThreadFactory THREAD_FACTORY = new CustomThreadFactory("ClientEventLoop", false); 23 | 24 | private final String ip; 25 | private final int port; 26 | private final EventLoopGroup clientGroup; 27 | private final NettyClient client; 28 | 29 | public NettyClientAdapter(NettyClient client) { 30 | this.ip = ProtocolConfig.getIp(); 31 | this.port = ProtocolConfig.getPort(); 32 | clientGroup = new NioEventLoopGroup(1, THREAD_FACTORY); 33 | this.client = client; 34 | } 35 | 36 | public void start() { 37 | connection(ip, port); 38 | } 39 | 40 | public void quit() { 41 | if(null != clientGroup) { 42 | clientGroup.shutdownGracefully(); 43 | } 44 | } 45 | 46 | public void reconnect() { 47 | 48 | new Thread( () -> { 49 | connection(ip, port); 50 | } 51 | ).start(); 52 | } 53 | 54 | private void connection(final String ip, final int port) { 55 | try { 56 | ChannelFuture cf = client.connect(clientGroup, ip, port); 57 | cf.addListener(new ChannelFutureListener() { 58 | @Override 59 | public void operationComplete(ChannelFuture future) throws Exception { 60 | if(future.isSuccess()) { 61 | LOGGER.info("client connect success. ip:{}, port:{}", ip, port); 62 | } else { 63 | LOGGER.error("connect fail.", future.cause()); 64 | reconnect(); 65 | } 66 | } 67 | }); 68 | } catch (Exception e) { 69 | reconnect(); 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/client/ProtobufNettyClient.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.client; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.ChannelInitializer; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 7 | import io.netty.handler.codec.protobuf.ProtobufEncoder; 8 | import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; 9 | import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; 10 | import io.netty.handler.timeout.IdleStateHandler; 11 | import org.lwl.netty.client.handler.ClientExceptionHandler; 12 | import org.lwl.netty.client.handler.protobuf.HeartbeatClientHandler; 13 | import org.lwl.netty.client.handler.protobuf.LoginReqHandler; 14 | import org.lwl.netty.codec.other.ProtocolDataDecoder; 15 | import org.lwl.netty.codec.other.ProtocolDataEncoder; 16 | import org.lwl.netty.config.ProtocolConfig; 17 | 18 | import java.util.concurrent.TimeUnit; 19 | 20 | /** 21 | * @author thinking_fioa 22 | * @createTime 2018/7/8 23 | * @description 24 | */ 25 | 26 | 27 | public class ProtobufNettyClient extends NettyClient { 28 | 29 | @Override 30 | public void initChannel0(Bootstrap bootstrap) { 31 | bootstrap.handler(new ProtobufChildChannelHandler()); 32 | } 33 | 34 | private static class ProtobufChildChannelHandler extends ChannelInitializer { 35 | @Override 36 | protected void initChannel(SocketChannel ch) throws Exception { 37 | // ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO)); 38 | ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); 39 | ch.pipeline().addLast(new ProtobufDecoder(org.lwl.netty.message.protobuf.ProtocolMessage.ProtocolMessageP.getDefaultInstance())); 40 | ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); 41 | ch.pipeline().addLast(new ProtobufEncoder()); 42 | ch.pipeline().addLast(new LoginReqHandler()); 43 | ch.pipeline().addLast(new IdleStateHandler(ProtocolConfig.getHeartbeatInterval(), ProtocolConfig.getHeartbeatInterval(), 0, TimeUnit.SECONDS)); 44 | ch.pipeline().addLast(new HeartbeatClientHandler()); 45 | // ch.pipeline().addLast(new ProtocolMsgSubHandler()); 46 | ch.pipeline().addLast(new ClientExceptionHandler()); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/client/handler/ClientExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.client.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/5/26 11 | * @description 处理客户端异常输出 12 | */ 13 | 14 | 15 | public class ClientExceptionHandler extends ChannelInboundHandlerAdapter { 16 | 17 | private static final Logger LOGGER = LogManager.getLogger(ClientExceptionHandler.class); 18 | 19 | @Override 20 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 21 | LOGGER.error("Client Handler happen exception.", cause); 22 | } 23 | 24 | @Override 25 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 26 | LOGGER.error("client close channel."); 27 | ctx.close(); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/client/handler/other/LoginReqHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.client.handler.other; 2 | 3 | import io.netty.channel.ChannelHandler; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.ChannelInboundHandlerAdapter; 6 | import org.apache.logging.log4j.LogManager; 7 | import org.apache.logging.log4j.Logger; 8 | import org.lwl.netty.config.ProtocolConfig; 9 | import org.lwl.netty.constant.MessageTypeEnum; 10 | import org.lwl.netty.message.ProtocolMessage; 11 | import org.lwl.netty.message.body.LoginReqBody; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/5/24 16 | * @description 登陆请求 17 | */ 18 | 19 | @ChannelHandler.Sharable 20 | public class LoginReqHandler extends ChannelInboundHandlerAdapter { 21 | private static final Logger LOGGER = LogManager.getLogger(LoginReqHandler.class); 22 | 23 | private static final String USERNAME = ProtocolConfig.getUserName(); 24 | private static final String PASSWORD = ProtocolConfig.getPassword(); 25 | 26 | @Override 27 | public void channelActive(ChannelHandlerContext ctx) { 28 | ProtocolMessage loginMsg = buildLoginReqMsg(); 29 | LOGGER.info("channel active. login req sent."); 30 | ctx.writeAndFlush(loginMsg); 31 | } 32 | 33 | @Override 34 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 35 | ProtocolMessage message = (ProtocolMessage) msg; 36 | final MessageTypeEnum msgType = message.getHeader().getMsgType(); 37 | if(MessageTypeEnum.LOGIN_RESP.equals(msgType)) { 38 | LOGGER.info("receive login resp."); 39 | } else { 40 | ctx.fireChannelRead(msg); 41 | } 42 | } 43 | 44 | private ProtocolMessage buildLoginReqMsg() { 45 | LoginReqBody loginReqBody = new LoginReqBody(); 46 | loginReqBody.setUserName(USERNAME); 47 | loginReqBody.setPassword(PASSWORD); 48 | 49 | return ProtocolMessage.createMsgOfEncode(loginReqBody); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/client/handler/other/ProtocolMsgSubHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.client.handler.other; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.constant.ProtocolDataType; 8 | import org.lwl.netty.message.ProtocolMessage; 9 | import org.lwl.netty.message.body.ProtocolSubBody; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/5/24 17 | * @description Protocol消息订阅和接收服务 18 | */ 19 | 20 | public class ProtocolMsgSubHandler extends ChannelInboundHandlerAdapter { 21 | private static final Logger LOGGER = LogManager.getLogger(ProtocolMsgSubHandler.class); 22 | 23 | @Override 24 | public void channelActive(ChannelHandlerContext ctx) { 25 | ProtocolMessage ptclSubMsg = buildPtclSubMsg(); 26 | LOGGER.info("MsgSub active. protocol msg sub sent"); 27 | ctx.writeAndFlush(ptclSubMsg); 28 | } 29 | 30 | private ProtocolMessage buildPtclSubMsg() { 31 | ProtocolSubBody subBody = new ProtocolSubBody(); 32 | List dataTypeList = new ArrayList(); 33 | dataTypeList.add(ProtocolDataType.NEWS); 34 | dataTypeList.add(ProtocolDataType.SPORTS); 35 | dataTypeList.add(ProtocolDataType.ENTERTAINMENT); 36 | 37 | return ProtocolMessage.createMsgOfEncode(subBody); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/client/handler/protobuf/ProtobufClientCodecHelper.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.client.handler.protobuf; 2 | 3 | import org.lwl.netty.message.protobuf.Header; 4 | import org.lwl.netty.message.protobuf.ProtocolMessage; 5 | import org.lwl.netty.message.protobuf.Tail; 6 | import org.lwl.netty.util.CommonUtil; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.concurrent.atomic.AtomicLong; 11 | 12 | /** 13 | * @author thinking_fioa 14 | * @createTime 2018/7/11 15 | * @description 帮助Protobuf编码和解码工具类 16 | */ 17 | 18 | final class ProtobufClientCodecHelper { 19 | 20 | private static final AtomicLong MSG_NUM = new AtomicLong(0); 21 | 22 | private ProtobufClientCodecHelper() { 23 | throw new IllegalAccessError("can not use constructor."); 24 | } 25 | 26 | public static Header.HeaderP.Builder generateHeaderBuilder(Header.MessageTypeEnum msgType) { 27 | Header.HeaderP.Builder headerBuilder = Header.HeaderP.newBuilder(); 28 | 29 | headerBuilder.setMsgNum(MSG_NUM.get()); 30 | headerBuilder.setMsgType(msgType); 31 | headerBuilder.setMsgTime(CommonUtil.nowTime()); 32 | // 下面的值,随机填。主要目的是证明协议支持多种类型格式 33 | headerBuilder.setFlag(2); 34 | headerBuilder.setOneByte(3); 35 | Map attachment = new HashMap<>(); 36 | attachment.put("name", "luweilin"); 37 | attachment.put("age", "20"); 38 | headerBuilder.putAllAttachment(attachment); 39 | 40 | return headerBuilder; 41 | } 42 | 43 | public static Tail.TailP.Builder generateTailBuilder(ProtocolMessage.ProtocolMessageP.Builder msgBuilder) { 44 | byte[] bytes = msgBuilder.build().toByteArray(); 45 | int checkSum = CommonUtil.calCheckSum(bytes); 46 | Tail.TailP.Builder tailBuilder = Tail.TailP.newBuilder(); 47 | tailBuilder.setCheckSum(checkSum); 48 | 49 | return tailBuilder; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/client/handler/protobuf/ProtocolMsgSubHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.client.handler.protobuf; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.message.protobuf.*; 8 | import org.lwl.netty.message.protobuf.ProtocolSubBody.ProtocolDataType; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/7/11 16 | * @description 17 | */ 18 | 19 | 20 | public class ProtocolMsgSubHandler extends ChannelInboundHandlerAdapter { 21 | private static final Logger LOGGER = LogManager.getLogger(ProtocolMsgSubHandler.class); 22 | 23 | @Override 24 | public void channelActive(ChannelHandlerContext ctx) { 25 | ProtocolMessage.ProtocolMessageP msg = buildPtclSubMsg(); 26 | LOGGER.info("MsgSub active. protocol msg sub sent."); 27 | ctx.writeAndFlush(msg); 28 | } 29 | 30 | private ProtocolMessage.ProtocolMessageP buildPtclSubMsg() { 31 | ProtocolMessage.ProtocolMessageP.Builder msgBuilder= ProtocolMessage.ProtocolMessageP.newBuilder(); 32 | // Header 33 | Header.HeaderP.Builder headerBuilder = ProtobufClientCodecHelper.generateHeaderBuilder(Header.MessageTypeEnum.PROTOCOL_SUB); 34 | msgBuilder.setHeader(headerBuilder); 35 | // Body 36 | ProtocolSubBody.ProtocolSubBodyP.Builder subBuilder = ProtocolSubBody.ProtocolSubBodyP.newBuilder(); 37 | List dataTypeList = new ArrayList<>(); 38 | dataTypeList.add(ProtocolDataType.NEWS); 39 | dataTypeList.add(ProtocolDataType.SPORTS); 40 | dataTypeList.add(ProtocolDataType.ENTERTAINMENT); 41 | subBuilder.addAllDataTypeList(dataTypeList); 42 | // Tail 43 | Tail.TailP.Builder tailBuilder = ProtobufClientCodecHelper.generateTailBuilder(msgBuilder); 44 | msgBuilder.setTail(tailBuilder); 45 | 46 | return msgBuilder.build(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/IMessageCodecUtil.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | 6 | import java.io.IOException; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/5/9 11 | * @description 12 | */ 13 | 14 | 15 | public interface IMessageCodecUtil { 16 | 17 | void encode(ChannelHandlerContext ctx, ByteBuf outByteBuf, T object) throws Exception; 18 | 19 | T decode(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws Exception; 20 | } 21 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/ProtocolDataDecoder.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.EncoderException; 6 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | import org.lwl.netty.constant.ProtocolConstant; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/4/26 14 | * @description 解码器 15 | */ 16 | 17 | 18 | public class ProtocolDataDecoder extends LengthFieldBasedFrameDecoder { 19 | private static final Logger LOGGER = LogManager.getLogger(ProtocolDataDecoder.class); 20 | 21 | private static final int MAX_FRAMELENGTH = ProtocolConstant.getMaxFramelength(); 22 | private static final int LENGTH_FIELD_OFFSET = ProtocolConstant.getLengthFieldOffset(); 23 | private static final int LENGTHFIELD_LENGTH = ProtocolConstant.getLengthfieldLength(); 24 | private static final int LENGTH_ADJUSTMENT = ProtocolConstant.getLengthAdjustment(); 25 | private static final int INITIAL_BYTES_TO_STRIP = ProtocolConstant.getInitialBytesToStrip(); 26 | 27 | private IMessageCodecUtil codecUtil; 28 | 29 | public ProtocolDataDecoder() { 30 | super(MAX_FRAMELENGTH, LENGTH_FIELD_OFFSET, LENGTHFIELD_LENGTH, LENGTH_ADJUSTMENT, INITIAL_BYTES_TO_STRIP); 31 | this.codecUtil = MessageCodecUtilFactory.getCodecUtil(); 32 | } 33 | 34 | @Override 35 | public Object decode(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws Exception{ 36 | ByteBuf frame = null; 37 | try { 38 | frame = (ByteBuf) super.decode(ctx, inByteBuf); 39 | if(null == frame) { 40 | return null; 41 | } 42 | 43 | return codecUtil.decode(ctx, frame); 44 | 45 | } catch (Throwable cause) { 46 | LOGGER.error("Decode error.", cause); 47 | throw new EncoderException("Decode error."); 48 | } finally { 49 | if(null != frame) { 50 | frame.release(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/ProtocolDataEncoder.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToByteEncoder; 6 | import org.apache.logging.log4j.LogManager; 7 | import org.apache.logging.log4j.Logger; 8 | import org.lwl.netty.message.Header; 9 | import org.lwl.netty.message.ProtocolMessage; 10 | import org.lwl.netty.util.CommonUtil; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author thinking_fioa 17 | * @createTime 2018/4/26 18 | * @description 编码器 19 | */ 20 | 21 | 22 | public class ProtocolDataEncoder extends MessageToByteEncoder { 23 | private static final Logger LOGGER = LogManager.getLogger(ProtocolDataEncoder.class); 24 | 25 | private long msgNum = 1; 26 | 27 | private IMessageCodecUtil codecUtil; 28 | 29 | public ProtocolDataEncoder() { 30 | this.codecUtil = MessageCodecUtilFactory.getCodecUtil(); 31 | } 32 | 33 | @Override 34 | protected void encode(ChannelHandlerContext ctx, ProtocolMessage protocolMessage, ByteBuf outByteBuf) throws Exception { 35 | if(null == protocolMessage || null == protocolMessage.getBody()) { 36 | LOGGER.error("protocolMessage is null. refuse encode"); 37 | 38 | return; 39 | } 40 | try { 41 | // 填写头协议 42 | fillInHeader(protocolMessage); 43 | 44 | codecUtil.encode(ctx, outByteBuf, protocolMessage); 45 | LOGGER.info("--> encode msgType:{}, msLen: {}", protocolMessage.getHeader().getMsgType(), outByteBuf.writerIndex()); 46 | } catch(Throwable cause) { 47 | LOGGER.error("Encode error.", cause); 48 | } 49 | 50 | } 51 | 52 | private void fillInHeader(ProtocolMessage protocolMessage) { 53 | Header header = protocolMessage.getHeader(); 54 | header.setMsgNum(msgNum++); 55 | header.setMsgType(protocolMessage.getBody().msgType()); 56 | header.setMsgTime(CommonUtil.nowTime()); 57 | 58 | // 下面的值,随机填。主要目的是证明协议支持多种类型格式 59 | header.setFlag((short)2); 60 | header.setOneByte((byte)3); 61 | 62 | Map attachment = new HashMap<>(); 63 | attachment.put("name", "thinking_fioa"); 64 | attachment.put("age", 18); 65 | 66 | header.getAttachment().putAll(attachment); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/KryoHolder.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | 5 | /** 6 | * @author thinking_fioa 7 | * @createTime 2018/5/17 8 | * @description Kryo编码器是一个非线程安全,所以使用ThreadLocal 9 | */ 10 | 11 | 12 | public class KryoHolder { 13 | private static ThreadLocal threadLocalKryo = new ThreadLocal(){ 14 | @Override 15 | protected Kryo initialValue() { 16 | Kryo kryo = new KryoReflectionFactory(); 17 | 18 | return kryo; 19 | } 20 | }; 21 | 22 | public static Kryo get() { 23 | return threadLocalKryo.get(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/HeaderKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | import org.lwl.netty.constant.MessageTypeEnum; 10 | import org.lwl.netty.message.Header; 11 | 12 | import java.util.Map; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/5/17 17 | * @description Kryo编码器。类: {@link Header} 18 | */ 19 | 20 | 21 | public class HeaderKryoSerializer extends Serializer
{ 22 | private static final Logger LOGGER = LogManager.getLogger(HeaderKryoSerializer.class); 23 | 24 | @Override 25 | public void write(Kryo kryo, Output output, Header header) { 26 | KryoEncoder.getInstance().writeLong(output, header.getMsgNum()); 27 | KryoEncoder.getInstance().writeByte(output, header.getMsgType().getMsgType()); 28 | KryoEncoder.getInstance().writeString(output, header.getMsgTime()); 29 | KryoEncoder.getInstance().writeShort(output, header.getFlag()); 30 | KryoEncoder.getInstance().writeByte(output, header.getOneByte()); 31 | KryoEncoder.getInstance().writeMap(kryo, output, header.getAttachment()); 32 | } 33 | 34 | @Override 35 | public Header read(Kryo kryo, Input input, Class
aClass) { 36 | long msgNum = KryoDecoder.getInstance().readLong(input); 37 | Byte msgType = KryoDecoder.getInstance().readByte(input); 38 | String msgTime = KryoDecoder.getInstance().readString(input); 39 | short flag = KryoDecoder.getInstance().readShort(input); 40 | byte oneByte = KryoDecoder.getInstance().readByte(input); 41 | Map attachment = KryoDecoder.getInstance().readMap(kryo, input); 42 | 43 | Header header = new Header(); 44 | header.setMsgNum(msgNum); 45 | header.setMsgType(MessageTypeEnum.getMsgTypeEnum(msgType)); 46 | header.setMsgTime(msgTime); 47 | header.setFlag(flag); 48 | header.setOneByte(oneByte); 49 | header.setAttachment(attachment); 50 | 51 | return header; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/KryoDecoder.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.Input; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/5/12 14 | * @description 15 | */ 16 | 17 | 18 | public class KryoDecoder { 19 | 20 | private static final KryoDecoder INSTANCE = new KryoDecoder(); 21 | 22 | public static KryoDecoder getInstance() { 23 | return INSTANCE; 24 | } 25 | 26 | @SuppressWarnings("unchecked") 27 | public List readList(Kryo kryo, Input input, Class clazz) { 28 | int size = input.readInt(); 29 | if(-1 == size) { 30 | return null; 31 | } 32 | if( 0 == size) { 33 | return new ArrayList<>(); 34 | } 35 | 36 | List list = new ArrayList<>(size); 37 | for(int i =0;i readMap(Kryo kryo, Input input) { 45 | int size = input.readInt(); 46 | if(-1 == size) { 47 | return null; 48 | } 49 | if(0 == size) { 50 | return new HashMap(); 51 | } 52 | 53 | Map valueMap = new HashMap(size); 54 | for(int i = 0; i { 22 | private static final Logger LOGGER = LogManager.getLogger(ProtocolMessageKryoSerializer.class); 23 | 24 | @Override 25 | public void write(Kryo kryo, Output output, ProtocolMessage protocolMessage) { 26 | KryoEncoder.getInstance().writeObject(kryo, output, protocolMessage.getHeader()); 27 | KryoEncoder.getInstance().writeObject(kryo, output, protocolMessage.getBody()); 28 | KryoEncoder.getInstance().writeObject(kryo, output, protocolMessage.getTail()); 29 | } 30 | 31 | @Override 32 | public ProtocolMessage read(Kryo kryo, Input input, Class aClass) { 33 | Header header = (Header)KryoDecoder.getInstance().readObject(kryo, input); 34 | Body body = (Body)KryoDecoder.getInstance().readObject(kryo, input); 35 | Tail tail = (Tail)KryoDecoder.getInstance().readObject(kryo, input); 36 | 37 | return ProtocolMessage.createMsgOfDecode(header, body, tail); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/TailKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.message.Tail; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/17 12 | * @description 13 | */ 14 | 15 | 16 | public class TailKryoSerializer extends Serializer { 17 | 18 | @Override 19 | public void write(Kryo kryo, Output output, Tail tail) { 20 | KryoEncoder.getInstance().writeInt(output, tail.getCheckSum()); 21 | } 22 | 23 | @Override 24 | public Tail read(Kryo kryo, Input input, Class aClass) { 25 | int checkSum = KryoDecoder.getInstance().readInt(input); 26 | 27 | Tail tail = new Tail(); 28 | tail.setCheckSum(checkSum); 29 | 30 | return tail; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/DefaultBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.message.Body; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/26 12 | * @description 13 | */ 14 | 15 | 16 | public final class DefaultBodyKryoSerializer extends Serializer { 17 | @Override 18 | public void write(Kryo kryo, Output output, Body body) { 19 | 20 | } 21 | 22 | @Override 23 | public Body read(Kryo kryo, Input input, Class aClass) { 24 | return new Body(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/HtReqBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.message.body.HeartbeatReqBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/6/10 12 | * @description 13 | */ 14 | 15 | 16 | public class HtReqBodyKryoSerializer extends Serializer { 17 | @Override 18 | public void write(Kryo kryo, Output output, HeartbeatReqBody heartbeatReqBody) { 19 | 20 | } 21 | 22 | @Override 23 | public HeartbeatReqBody read(Kryo kryo, Input input, Class aClass) { 24 | return new HeartbeatReqBody(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/HtRespBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.message.body.HeartbeatRespBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/6/10 12 | * @description 13 | */ 14 | 15 | 16 | public class HtRespBodyKryoSerializer extends Serializer { 17 | @Override 18 | public void write(Kryo kryo, Output output, HeartbeatRespBody heartbeatRespBody) { 19 | 20 | } 21 | 22 | @Override 23 | public HeartbeatRespBody read(Kryo kryo, Input input, Class aClass) { 24 | return new HeartbeatRespBody(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/LoginReqBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.codec.other.kryo.serialize.KryoDecoder; 8 | import org.lwl.netty.codec.other.kryo.serialize.KryoEncoder; 9 | import org.lwl.netty.message.body.LoginReqBody; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/6/10 14 | * @description 15 | */ 16 | 17 | 18 | public class LoginReqBodyKryoSerializer extends Serializer { 19 | @Override 20 | public void write(Kryo kryo, Output output, LoginReqBody login) { 21 | KryoEncoder.getInstance().writeString(output, login.getUserName()); 22 | KryoEncoder.getInstance().writeString(output, login.getPassword()); 23 | } 24 | 25 | @Override 26 | public LoginReqBody read(Kryo kryo, Input input, Class aClass) { 27 | String userName = KryoDecoder.getInstance().readString(input); 28 | String password = KryoDecoder.getInstance().readString(input); 29 | 30 | LoginReqBody loginReqBody = new LoginReqBody(); 31 | loginReqBody.setUserName(userName); 32 | loginReqBody.setPassword(password); 33 | 34 | return loginReqBody; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/LoginRespBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.message.body.LoginRespBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/6/10 12 | * @description 13 | */ 14 | 15 | 16 | public class LoginRespBodyKryoSerializer extends Serializer { 17 | @Override 18 | public void write(Kryo kryo, Output output, LoginRespBody loginRespBody) { 19 | 20 | } 21 | 22 | @Override 23 | public LoginRespBody read(Kryo kryo, Input input, Class aClass) { 24 | return new LoginRespBody(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/LogoutBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.message.body.LogoutBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/6/10 12 | * @description 13 | */ 14 | 15 | 16 | public class LogoutBodyKryoSerializer extends Serializer { 17 | @Override 18 | public void write(Kryo kryo, Output output, LogoutBody logoutBody) { 19 | 20 | } 21 | 22 | @Override 23 | public LogoutBody read(Kryo kryo, Input input, Class aClass) { 24 | return new LogoutBody(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/ProtocolDataBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.codec.other.kryo.serialize.KryoDecoder; 8 | import org.lwl.netty.codec.other.kryo.serialize.KryoEncoder; 9 | import org.lwl.netty.message.body.ProtocolDataBody; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/6/10 14 | * @description 15 | */ 16 | 17 | 18 | public class ProtocolDataBodyKryoSerializer extends Serializer { 19 | @Override 20 | public void write(Kryo kryo, Output output, ProtocolDataBody dataBody) { 21 | KryoEncoder.getInstance().writeLong(output, dataBody.getPkgSum()); 22 | KryoEncoder.getInstance().writeLong(output, dataBody.getPkgSequenceNum()); 23 | KryoEncoder.getInstance().writeInt(output, dataBody.getContentLen()); 24 | KryoEncoder.getInstance().writeBytes(output, dataBody.getContent()); 25 | } 26 | 27 | @Override 28 | public ProtocolDataBody read(Kryo kryo, Input input, Class aClass) { 29 | long pkgSum = KryoDecoder.getInstance().readLong(input); 30 | long pkgSequenceNum = KryoDecoder.getInstance().readLong(input); 31 | int contentLen = KryoDecoder.getInstance().readInt(input); 32 | byte [] content = new byte[contentLen]; 33 | KryoDecoder.getInstance().readBytes(input, content); 34 | 35 | ProtocolDataBody dataBody = new ProtocolDataBody(); 36 | dataBody.setPkgSum(pkgSum); 37 | dataBody.setPkgSequenceNum(pkgSequenceNum); 38 | dataBody.setContentLen(contentLen); 39 | dataBody.setContent(content); 40 | 41 | return new ProtocolDataBody(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/kryo/serialize/body/ProtocolSubBodyKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.kryo.serialize.body; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.Serializer; 5 | import com.esotericsoftware.kryo.io.Input; 6 | import com.esotericsoftware.kryo.io.Output; 7 | import org.lwl.netty.codec.other.kryo.serialize.KryoDecoder; 8 | import org.lwl.netty.codec.other.kryo.serialize.KryoEncoder; 9 | import org.lwl.netty.constant.ProtocolDataType; 10 | import org.lwl.netty.message.body.ProtocolSubBody; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/6/10 17 | * @description 18 | */ 19 | 20 | 21 | public class ProtocolSubBodyKryoSerializer extends Serializer { 22 | @Override 23 | public void write(Kryo kryo, Output output, ProtocolSubBody subBody) { 24 | KryoEncoder.getInstance().writeList(kryo, output, subBody.getDataTypeList()); 25 | } 26 | 27 | @Override 28 | public ProtocolSubBody read(Kryo kryo, Input input, Class aClass) { 29 | List dataTypeList = KryoDecoder.getInstance().readList(kryo, input, ProtocolDataType.class); 30 | 31 | ProtocolSubBody subBody = new ProtocolSubBody(); 32 | subBody.setDataTypeList(dataTypeList); 33 | 34 | return new ProtocolSubBody(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/MarshallingDecoderAdapter.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.marshalling.MarshallingDecoder; 6 | import io.netty.handler.codec.marshalling.UnmarshallerProvider; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/5/13 11 | * @description 12 | */ 13 | 14 | 15 | public class MarshallingDecoderAdapter extends MarshallingDecoder{ 16 | 17 | public MarshallingDecoderAdapter(UnmarshallerProvider provider) { 18 | super(provider); 19 | } 20 | 21 | public MarshallingDecoderAdapter(UnmarshallerProvider provider, int maxObjectSize) { 22 | super(provider, maxObjectSize); 23 | } 24 | 25 | @Override 26 | public Object decode(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws Exception { 27 | return super.decode(ctx, inByteBuf); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/MarshallingEncoderAdapter.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.marshalling.MarshallerProvider; 6 | import io.netty.handler.codec.marshalling.MarshallingEncoder; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/5/13 11 | * @description 12 | */ 13 | 14 | 15 | public class MarshallingEncoderAdapter extends MarshallingEncoder { 16 | 17 | public MarshallingEncoderAdapter(MarshallerProvider provider) { 18 | super(provider); 19 | } 20 | 21 | @Override 22 | public void encode(ChannelHandlerContext ctx, Object msg, ByteBuf outByteBuf) throws Exception { 23 | super.encode(ctx, msg, outByteBuf); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/HeaderMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.MslDecoder; 6 | import org.lwl.netty.codec.other.marshalling.MslEncoder; 7 | import org.lwl.netty.constant.MessageTypeEnum; 8 | import org.lwl.netty.message.Header; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * @author thinking_fioa 14 | * @createTime 2018/5/15 15 | * @description 16 | */ 17 | 18 | public class HeaderMslSerializer { 19 | 20 | private static final HeaderMslSerializer INSTANCE = new HeaderMslSerializer(); 21 | private HeaderMslSerializer(){} 22 | 23 | public static HeaderMslSerializer getInstance() { 24 | return INSTANCE; 25 | } 26 | 27 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Header header) throws Exception { 28 | MslEncoder.getInstance().writeLong(outByteBuf, header.getMsgNum()); 29 | MslEncoder.getInstance().writeByte(outByteBuf, header.getMsgType().getMsgType()); 30 | MslEncoder.getInstance().writeString(outByteBuf, header.getMsgTime()); 31 | MslEncoder.getInstance().writeShort(outByteBuf, header.getFlag()); 32 | MslEncoder.getInstance().writeByte(outByteBuf, header.getOneByte()); 33 | MslEncoder.getInstance().writeMap(ctx, outByteBuf, header.getAttachment()); 34 | } 35 | 36 | public Header deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws Exception{ 37 | long msgNum = MslDecoder.getInstance().readLong(inByteBuf); 38 | Byte msgType = MslDecoder.getInstance().readByte(inByteBuf); 39 | String msgTime = MslDecoder.getInstance().readString(inByteBuf); 40 | short flag = MslDecoder.getInstance().readShort(inByteBuf); 41 | byte oneByte = MslDecoder.getInstance().readByte(inByteBuf); 42 | Map attachment = MslDecoder.getInstance().readMap(ctx, inByteBuf); 43 | 44 | Header header = new Header(); 45 | header.setMsgNum(msgNum); 46 | header.setMsgType(MessageTypeEnum.getMsgTypeEnum(msgType)); 47 | header.setMsgTime(msgTime); 48 | header.setFlag(flag); 49 | header.setOneByte(oneByte); 50 | header.setAttachment(attachment); 51 | 52 | return header; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/IBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.message.Body; 6 | 7 | /** 8 | * @author thinking_fioa 9 | * @createTime 2018/5/15 10 | * @description 11 | */ 12 | 13 | 14 | public interface IBodyMslSerializer { 15 | 16 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) throws Exception; 17 | 18 | public T deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws Exception; 19 | } 20 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/TailMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.MslDecoder; 6 | import org.lwl.netty.codec.other.marshalling.MslEncoder; 7 | import org.lwl.netty.message.Tail; 8 | import org.lwl.netty.util.CommonUtil; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/5/15 13 | * @description 14 | */ 15 | 16 | 17 | public class TailMslSerializer { 18 | 19 | private static final TailMslSerializer INSTANCE = new TailMslSerializer(); 20 | private TailMslSerializer(){} 21 | 22 | public static TailMslSerializer getInstance() { 23 | return INSTANCE; 24 | } 25 | 26 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Tail msg) throws Exception { 27 | int checkSum = CommonUtil.calCheckSum(outByteBuf, outByteBuf.writerIndex()); 28 | MslEncoder.getInstance().writeInt(outByteBuf, checkSum); 29 | } 30 | 31 | public Tail deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws Exception { 32 | int checkSum = MslDecoder.getInstance().readInt(inByteBuf); 33 | 34 | Tail tail = new Tail(); 35 | tail.setCheckSum(checkSum); 36 | 37 | return tail; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/DefaultBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 6 | import org.lwl.netty.message.Body; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/5/26 11 | * @description 12 | */ 13 | 14 | 15 | public final class DefaultBodyMslSerializer implements IBodyMslSerializer { 16 | 17 | private static final DefaultBodyMslSerializer INSTANCE = new DefaultBodyMslSerializer(); 18 | private DefaultBodyMslSerializer(){} 19 | 20 | public static DefaultBodyMslSerializer getInstance() { 21 | return INSTANCE; 22 | } 23 | 24 | @Override 25 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) { 26 | 27 | } 28 | 29 | @Override 30 | public Body deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) { 31 | return new Body(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/HeartbeatReqBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 6 | import org.lwl.netty.message.Body; 7 | import org.lwl.netty.message.body.HeartbeatReqBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/26 12 | * @description 13 | */ 14 | 15 | 16 | public final class HeartbeatReqBodyMslSerializer implements IBodyMslSerializer { 17 | 18 | private static final HeartbeatReqBodyMslSerializer INSTANCE = new HeartbeatReqBodyMslSerializer(); 19 | private HeartbeatReqBodyMslSerializer(){} 20 | 21 | public static HeartbeatReqBodyMslSerializer getInstance() { 22 | return INSTANCE; 23 | } 24 | 25 | 26 | @Override 27 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) { 28 | 29 | } 30 | 31 | @Override 32 | public HeartbeatReqBody deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) { 33 | return new HeartbeatReqBody(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/HeartbeatRespBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 6 | import org.lwl.netty.message.Body; 7 | import org.lwl.netty.message.body.HeartbeatRespBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/26 12 | * @description 13 | */ 14 | 15 | 16 | public final class HeartbeatRespBodyMslSerializer implements IBodyMslSerializer { 17 | 18 | private static final HeartbeatRespBodyMslSerializer INSTANCE = new HeartbeatRespBodyMslSerializer(); 19 | private HeartbeatRespBodyMslSerializer(){} 20 | 21 | public static HeartbeatRespBodyMslSerializer getInstance() { 22 | return INSTANCE; 23 | } 24 | 25 | 26 | @Override 27 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) { 28 | 29 | } 30 | 31 | @Override 32 | public HeartbeatRespBody deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) { 33 | return new HeartbeatRespBody(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/LoginReqBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.MslDecoder; 6 | import org.lwl.netty.codec.other.marshalling.MslEncoder; 7 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 8 | import org.lwl.netty.message.Body; 9 | import org.lwl.netty.message.body.LoginReqBody; 10 | 11 | import java.io.UnsupportedEncodingException; 12 | 13 | /** 14 | * @author thinking_fioa 15 | * @createTime 2018/5/26 16 | * @description 17 | */ 18 | 19 | 20 | public final class LoginReqBodyMslSerializer implements IBodyMslSerializer { 21 | 22 | private static final LoginReqBodyMslSerializer INSTANCE = new LoginReqBodyMslSerializer(); 23 | private LoginReqBodyMslSerializer(){} 24 | 25 | public static LoginReqBodyMslSerializer getInstance() { 26 | return INSTANCE; 27 | } 28 | 29 | 30 | @Override 31 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) throws UnsupportedEncodingException { 32 | LoginReqBody login = (LoginReqBody)body; 33 | MslEncoder.getInstance().writeString(outByteBuf, login.getUserName()); 34 | MslEncoder.getInstance().writeString(outByteBuf, login.getPassword()); 35 | } 36 | 37 | @Override 38 | public LoginReqBody deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws UnsupportedEncodingException { 39 | String userName = MslDecoder.getInstance().readString(inByteBuf); 40 | String password = MslDecoder.getInstance().readString(inByteBuf); 41 | 42 | LoginReqBody loginReqBody = new LoginReqBody(); 43 | loginReqBody.setUserName(userName); 44 | loginReqBody.setPassword(password); 45 | 46 | return loginReqBody; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/LoginRespBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 6 | import org.lwl.netty.message.Body; 7 | import org.lwl.netty.message.body.LoginRespBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/26 12 | * @description 13 | */ 14 | 15 | 16 | public final class LoginRespBodyMslSerializer implements IBodyMslSerializer { 17 | 18 | private static final LoginRespBodyMslSerializer INSTANCE = new LoginRespBodyMslSerializer(); 19 | private LoginRespBodyMslSerializer(){} 20 | 21 | public static LoginRespBodyMslSerializer getInstance() { 22 | return INSTANCE; 23 | } 24 | 25 | 26 | @Override 27 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) { 28 | 29 | } 30 | 31 | @Override 32 | public LoginRespBody deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) { 33 | return new LoginRespBody(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/LogoutBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 6 | import org.lwl.netty.message.Body; 7 | import org.lwl.netty.message.body.LogoutBody; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/26 12 | * @description 13 | */ 14 | 15 | 16 | public final class LogoutBodyMslSerializer implements IBodyMslSerializer { 17 | 18 | private static final LogoutBodyMslSerializer INSTANCE = new LogoutBodyMslSerializer(); 19 | private LogoutBodyMslSerializer(){} 20 | 21 | public static LogoutBodyMslSerializer getInstance() { 22 | return INSTANCE; 23 | } 24 | 25 | 26 | @Override 27 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) { 28 | 29 | } 30 | 31 | @Override 32 | public LogoutBody deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) { 33 | return new LogoutBody(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/ProtocolDataBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.MslDecoder; 6 | import org.lwl.netty.codec.other.marshalling.MslEncoder; 7 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 8 | import org.lwl.netty.message.Body; 9 | import org.lwl.netty.message.body.ProtocolDataBody; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/5/26 14 | * @description 15 | */ 16 | 17 | 18 | public final class ProtocolDataBodyMslSerializer implements IBodyMslSerializer { 19 | 20 | private static final ProtocolDataBodyMslSerializer INSTANCE = new ProtocolDataBodyMslSerializer(); 21 | private ProtocolDataBodyMslSerializer(){} 22 | 23 | public static ProtocolDataBodyMslSerializer getInstance() { 24 | return INSTANCE; 25 | } 26 | 27 | @Override 28 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) { 29 | ProtocolDataBody dataBody = (ProtocolDataBody)body; 30 | 31 | MslEncoder.getInstance().writeLong(outByteBuf, dataBody.getPkgSum()); 32 | MslEncoder.getInstance().writeLong(outByteBuf, dataBody.getPkgSequenceNum()); 33 | MslEncoder.getInstance().writeInt(outByteBuf, dataBody.getContentLen()); 34 | MslEncoder.getInstance().writeBytes(outByteBuf, dataBody.getContent()); 35 | } 36 | 37 | @Override 38 | public ProtocolDataBody deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) { 39 | long pkgSum = MslDecoder.getInstance().readLong(inByteBuf); 40 | long pkgSequenceNum = MslDecoder.getInstance().readLong(inByteBuf); 41 | int contentLen = MslDecoder.getInstance().readInt(inByteBuf); 42 | byte [] content = new byte[contentLen]; 43 | MslDecoder.getInstance().readBytes(inByteBuf, content); 44 | 45 | ProtocolDataBody dataBody = new ProtocolDataBody(); 46 | dataBody.setPkgSum(pkgSum); 47 | dataBody.setPkgSequenceNum(pkgSequenceNum); 48 | dataBody.setContentLen(contentLen); 49 | dataBody.setContent(content); 50 | 51 | return new ProtocolDataBody(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/other/marshalling/serialize/body/ProtocolSubBodyMslSerializer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.other.marshalling.serialize.body; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.lwl.netty.codec.other.marshalling.MslDecoder; 6 | import org.lwl.netty.codec.other.marshalling.MslEncoder; 7 | import org.lwl.netty.codec.other.marshalling.serialize.IBodyMslSerializer; 8 | import org.lwl.netty.constant.ProtocolDataType; 9 | import org.lwl.netty.message.Body; 10 | import org.lwl.netty.message.body.ProtocolSubBody; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/5/26 17 | * @description 18 | */ 19 | 20 | 21 | public final class ProtocolSubBodyMslSerializer implements IBodyMslSerializer { 22 | 23 | private static final ProtocolSubBodyMslSerializer INSTANCE = new ProtocolSubBodyMslSerializer(); 24 | private ProtocolSubBodyMslSerializer(){} 25 | 26 | public static ProtocolSubBodyMslSerializer getInstance() { 27 | return INSTANCE; 28 | } 29 | 30 | 31 | @Override 32 | public void serialize(ChannelHandlerContext ctx, ByteBuf outByteBuf, Body body) throws Exception { 33 | ProtocolSubBody subBody = (ProtocolSubBody)body; 34 | MslEncoder.getInstance().writeList(ctx, outByteBuf, subBody.getDataTypeList()); 35 | } 36 | 37 | @Override 38 | public ProtocolSubBody deserialize(ChannelHandlerContext ctx, ByteBuf inByteBuf) throws Exception { 39 | 40 | List dataTypeList = MslDecoder.getInstance().readList(ctx, inByteBuf, ProtocolDataType.class); 41 | ProtocolSubBody subBody = new ProtocolSubBody(); 42 | subBody.setDataTypeList(dataTypeList); 43 | 44 | return new ProtocolSubBody(); 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/codec/protobuf/ProtobufPostDecoder.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.codec.protobuf; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/7/15 6 | * @description Protobuf解码器后做的校验。比如:checkSum校验 7 | */ 8 | 9 | 10 | public class ProtobufPostDecoder { 11 | } 12 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/config/BaseConfig.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.config; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | import java.io.IOException; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Properties; 10 | 11 | /** 12 | * @author thinking_fioa 13 | * @createTime 2018/5/15 14 | * @description 15 | */ 16 | 17 | 18 | public class BaseConfig { 19 | private static final Logger LOGGER = LogManager.getLogger(BaseConfig.class); 20 | 21 | public static String getStringProperty(Map props, String key, String defaultVal) { 22 | Object value = props.get(key); 23 | if(null == value) { 24 | return defaultVal; 25 | } 26 | 27 | return String.valueOf(props.get(key)).trim(); 28 | } 29 | 30 | public static int getIntProperty(Map props, String key, int defaultVal) { 31 | Object value = props.get(key); 32 | if(null == value) { 33 | return defaultVal; 34 | } 35 | 36 | return Integer.parseInt(props.get(key).trim()); 37 | } 38 | 39 | public static long getLongProperty(Map props, String key, long defaultVal) { 40 | Object value = props.get(key); 41 | if(null == value) { 42 | return defaultVal; 43 | } 44 | 45 | return Long.parseLong(props.get(key).trim()); 46 | } 47 | 48 | public static byte getByteProperty(Map props, String key, byte defaultVal) { 49 | Object value = props.get(key); 50 | if(null == value) { 51 | return defaultVal; 52 | } 53 | 54 | return Byte.parseByte(props.get(key).trim()); 55 | } 56 | 57 | public static boolean getBooleanProperty(Map props, String key, Boolean defaultVal) { 58 | Object value = props.get(key); 59 | if(null == value) { 60 | return defaultVal; 61 | } 62 | 63 | return Boolean.parseBoolean(props.get(key).trim()); 64 | } 65 | 66 | public static Map getConfigSettings(Properties pros) throws IOException { 67 | Map map = new HashMap(); 68 | for (Map.Entry entry : pros.entrySet()) { 69 | String key = String.valueOf(entry.getKey()).trim(); 70 | String value = String.valueOf(pros.get(key)); 71 | map.put(key, value); 72 | } 73 | 74 | return map; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/constant/MessageCodecTypeEnum.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.constant; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/4/24 6 | * @description 7 | */ 8 | 9 | 10 | public enum MessageCodecTypeEnum { 11 | // Kryo 编码 12 | KRYO("kryo"), 13 | // Marshalling 编码 14 | MARSHALLING("marshalling"), 15 | // Protobuf 编码 16 | PROTOBUF("protobuf"), 17 | // Thrift 编码 18 | THRIFT("thrift"), 19 | // avro 编码 20 | AVRO("avro"), 21 | // 二进制编码 22 | BINARY_CODEC("binary"); 23 | 24 | 25 | MessageCodecTypeEnum(final String codecType) { 26 | this.codecType = codecType; 27 | } 28 | 29 | private final String codecType; 30 | 31 | public String getCodecType() { 32 | return codecType; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/constant/MessageTypeEnum.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.constant; 2 | 3 | import java.util.EnumMap; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * @author thinking_fioa 9 | * @createTime 2018/4/21 10 | * @description 定义消息传输中消息类型常量 11 | */ 12 | 13 | 14 | public enum MessageTypeEnum { 15 | 16 | /** 17 | * Unknown 消息类型 18 | */ 19 | UNKNOWN((byte)0, "unknown"), 20 | 21 | /** 22 | * 登陆消息 23 | */ 24 | LOGIN_REQ((byte)1, "loginReq"), 25 | 26 | /** 27 | * 登陆响应 28 | */ 29 | LOGIN_RESP((byte)2, "loginResp"), 30 | 31 | /** 32 | * 注销 33 | */ 34 | LOGOUT((byte)3, "logout"), 35 | 36 | /** 37 | * 心跳请求 38 | */ 39 | HEARTBEAT_REQ((byte)4, "heartbeatReq"), 40 | 41 | /** 42 | * 心跳响应 43 | */ 44 | HEARTBEAT_RESP((byte)5, "heartbeatResp"), 45 | 46 | /** 47 | * 协议请求 48 | */ 49 | PROTOCOL_SUB((byte)6, "protocolSub"), 50 | 51 | /** 52 | * 协议数据消息 53 | */ 54 | PROTOCOL_DATA((byte)7, "protocolData") 55 | ; 56 | 57 | MessageTypeEnum(final byte type, final String desc) { 58 | this.msgType = type; 59 | this.desc = desc; 60 | } 61 | 62 | private final byte msgType; 63 | 64 | private final String desc; 65 | 66 | /** 67 | * 根据msgType类型,获取{@code MessageTypeEnum}
68 | * 使用Hashmap缓存,提高缓存 69 | * @param msgType 70 | * @return 71 | */ 72 | public static MessageTypeEnum getMsgTypeEnum(final Byte msgType) { 73 | if(null == msgType ) { 74 | return MessageTypeEnum.UNKNOWN; 75 | } 76 | 77 | 78 | return MessageTypeHolder.getMsgTypeEnum(msgType); 79 | } 80 | 81 | public byte getMsgType() { 82 | return msgType; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return desc; 88 | } 89 | 90 | private static class MessageTypeHolder { 91 | private static Map messageTypeMap; 92 | static { 93 | messageTypeMap = new HashMap<>(); 94 | for(MessageTypeEnum type: MessageTypeEnum.values()) { 95 | messageTypeMap.put(type.getMsgType(), type); 96 | } 97 | } 98 | 99 | public static MessageTypeEnum getMsgTypeEnum(Byte key) { 100 | if(messageTypeMap.containsKey(key)) { 101 | return messageTypeMap.get(key); 102 | } 103 | return MessageTypeEnum.UNKNOWN; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/constant/ProtocolConstant.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.constant; 2 | 3 | import org.lwl.netty.config.ProtocolConfig; 4 | 5 | /** 6 | * @author thinking_fioa 7 | * @createTime 2018/4/22 8 | * @description 私有协议中配置的信息 9 | */ 10 | 11 | 12 | public final class ProtocolConstant { 13 | // can't use 14 | private ProtocolConstant() { 15 | throw new IllegalAccessError("static class, can not use constructor."); 16 | } 17 | 18 | /** 19 | * @link LengthFieldBasedFrameDecoder} 使用的参数. 20 | * 最大消息字节数。4K = 4 * 1024 21 | */ 22 | private static final int MAX_FRAMELENGTH = ProtocolConfig.getPkgMaxLen(); 23 | private static final int LENGTH_FIELD_OFFSET = 0; 24 | private static final int LENGTHFIELD_LENGTH = 4; 25 | private static final int LENGTH_ADJUSTMENT = -4; 26 | private static final int INITIAL_BYTES_TO_STRIP = 0; 27 | 28 | /** 29 | * 序列化/反序列化方式 30 | */ 31 | private static final String CODEC_TYPE = MessageCodecTypeEnum.KRYO.getCodecType(); 32 | 33 | public static int getMaxFramelength() { 34 | return MAX_FRAMELENGTH; 35 | } 36 | 37 | public static int getLengthFieldOffset() { 38 | return LENGTH_FIELD_OFFSET; 39 | } 40 | 41 | public static int getLengthfieldLength() { 42 | return LENGTHFIELD_LENGTH; 43 | } 44 | 45 | public static int getLengthAdjustment() { 46 | return LENGTH_ADJUSTMENT; 47 | } 48 | 49 | public static int getInitialBytesToStrip() { 50 | return INITIAL_BYTES_TO_STRIP; 51 | } 52 | 53 | public static String getCodecType() { 54 | return CODEC_TYPE; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/constant/ProtocolDataType.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.constant; 2 | 3 | import java.util.EnumMap; 4 | import java.lang.Short; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/5/27 11 | * @description 私有协议数据类型,供Client端订阅,目前有:新闻,体育,娱乐。 12 | */ 13 | 14 | 15 | public enum ProtocolDataType { 16 | /** 17 | * 新闻 18 | */ 19 | NEWS((short)1, "news") , 20 | /** 21 | * 体育 22 | */ 23 | SPORTS((short)2, "sports"), 24 | /** 25 | * 娱乐 26 | */ 27 | ENTERTAINMENT((short)3, "entertainment"); 28 | 29 | private final short type; 30 | private final String typeDesc; 31 | 32 | private ProtocolDataType(short type, String typeDesc) { 33 | this.type = type; 34 | this.typeDesc = typeDesc; 35 | } 36 | 37 | /** 38 | * 根据type类型,获取{@code ProtocolDataType} 39 | * @param type 类型 40 | * @return 未找到类型,返回null 41 | */ 42 | public static ProtocolDataType getDataType(final short type) { 43 | return ProtocolDataTypeHolder.getDataType(type); 44 | } 45 | 46 | public short getType() { 47 | return type; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return typeDesc; 53 | } 54 | 55 | /** 56 | * 利用Map机制,加快查找 57 | */ 58 | private static class ProtocolDataTypeHolder { 59 | 60 | private final static Map dataTypeMap; 61 | 62 | static { 63 | dataTypeMap = new HashMap<>(); 64 | for(ProtocolDataType dataType: ProtocolDataType.values()) { 65 | dataTypeMap.put(dataType.type, dataType); 66 | } 67 | } 68 | 69 | private static ProtocolDataType getDataType(final short typeKey) { 70 | return dataTypeMap.get(typeKey); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/Body.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | 5 | /** 6 | * @author thinking_fioa 7 | * @createTime 2018/5/9 8 | * @description 9 | */ 10 | 11 | 12 | public class Body { 13 | 14 | public MessageTypeEnum msgType() { 15 | return MessageTypeEnum.UNKNOWN; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/Header.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/4/21 11 | * @description 消息头 12 | */ 13 | 14 | 15 | public class Header { 16 | /** 17 | * 发送消息数目 18 | */ 19 | private long msgNum; 20 | 21 | /** 22 | * 消息类型,{@code MessageTypeEnum} 23 | */ 24 | private MessageTypeEnum msgType; 25 | 26 | /** 27 | * 消息时间,格式: 28 | */ 29 | private String msgTime; 30 | 31 | /** 32 | * short类型占位符 33 | */ 34 | private short flag; 35 | 36 | /** 37 | * Byte类型占位符 38 | */ 39 | private byte oneByte; 40 | 41 | /** 42 | * 扩展字段,允许动态添加 43 | */ 44 | private Map attachment = new HashMap(); 45 | 46 | public long getMsgNum() { 47 | return msgNum; 48 | } 49 | 50 | public void setMsgNum(long msgNum) { 51 | this.msgNum = msgNum; 52 | } 53 | 54 | public Map getAttachment() { 55 | return attachment; 56 | } 57 | 58 | public void setAttachment(Map attachment) { 59 | this.attachment = attachment; 60 | } 61 | 62 | public short getFlag() { 63 | return flag; 64 | } 65 | 66 | public void setFlag(short flag) { 67 | this.flag = flag; 68 | } 69 | 70 | public MessageTypeEnum getMsgType() { 71 | return msgType; 72 | } 73 | 74 | public void setMsgType(MessageTypeEnum msgType) { 75 | this.msgType = msgType; 76 | } 77 | 78 | public String getMsgTime() { 79 | return msgTime; 80 | } 81 | 82 | public void setMsgTime(String msgTime) { 83 | this.msgTime = msgTime; 84 | } 85 | 86 | public byte getOneByte() { 87 | return oneByte; 88 | } 89 | 90 | public void setOneByte(byte oneByte) { 91 | this.oneByte = oneByte; 92 | } 93 | 94 | @Override 95 | public String toString() { 96 | StringBuilder sb = new StringBuilder(); 97 | sb.append("Header ["); 98 | sb.append("msgNum=").append(msgNum); 99 | sb.append(", msgType=").append(msgType); 100 | sb.append(", flag=").append(flag); 101 | sb.append(", oneByte=").append(oneByte); 102 | sb.append(", attachment").append(attachment).append("]"); 103 | 104 | return sb.toString(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/ProtocolMessage.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/4/21 6 | * @description 自定义消息格式消息 7 | */ 8 | 9 | 10 | public class ProtocolMessage { 11 | 12 | private Header header; 13 | 14 | private Body body; 15 | 16 | private Tail tail; 17 | 18 | private ProtocolMessage(Header header, Body body, Tail tail) { 19 | this.header = header; 20 | this.body = body; 21 | this.tail = tail; 22 | } 23 | 24 | private ProtocolMessage(Body body) { 25 | this.header = new Header(); 26 | this.body = body; 27 | this.tail = new Tail(); 28 | } 29 | 30 | public static ProtocolMessage createMsgOfEncode(Body body) { 31 | return new ProtocolMessage(body); 32 | } 33 | 34 | public static ProtocolMessage createMsgOfDecode(Header header, Body body, Tail tail) { 35 | return new ProtocolMessage(header, body, tail); 36 | } 37 | 38 | public Header getHeader() { 39 | return header; 40 | } 41 | 42 | public void setHeader(Header header) { 43 | this.header = header; 44 | } 45 | 46 | public Body getBody() { 47 | return body; 48 | } 49 | 50 | public void setBody(Body body) { 51 | this.body = body; 52 | } 53 | 54 | public Tail getTail() { 55 | return tail; 56 | } 57 | 58 | public void setTail(Tail tail) { 59 | this.tail = tail; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | return "ProtocolMessage: " + header.toString() + body.toString() + tail.toString(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/Tail.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/4/21 6 | * @description 消息体尾部 7 | */ 8 | 9 | 10 | public class Tail { 11 | 12 | private int checkSum; 13 | 14 | public int getCheckSum() { 15 | return checkSum; 16 | } 17 | 18 | public void setCheckSum(int checkSum) { 19 | this.checkSum = checkSum; 20 | } 21 | 22 | /** 23 | * 属性字节数 24 | * @return 25 | */ 26 | public static int byteSize() { 27 | return 4; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | StringBuilder sb = new StringBuilder(); 33 | sb.append("Tail ["); 34 | sb.append("checkSum=").append(checkSum).append("]"); 35 | 36 | return sb.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/body/HeartbeatReqBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message.body; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | import org.lwl.netty.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/26 9 | * @description 心跳数据 10 | */ 11 | 12 | 13 | public class HeartbeatReqBody extends Body { 14 | // nothing 15 | 16 | @Override 17 | public MessageTypeEnum msgType() { 18 | return MessageTypeEnum.HEARTBEAT_REQ; 19 | } 20 | 21 | @Override 22 | public String toString(){ 23 | 24 | return "HeartbeatReqBody []"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/body/HeartbeatRespBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message.body; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | import org.lwl.netty.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/26 9 | * @description 心跳数据 10 | */ 11 | 12 | 13 | public class HeartbeatRespBody extends Body { 14 | // nothing 15 | 16 | @Override 17 | public MessageTypeEnum msgType() { 18 | return MessageTypeEnum.HEARTBEAT_RESP; 19 | } 20 | 21 | @Override 22 | public String toString(){ 23 | 24 | return "HeartbeatRespBody []"; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/body/LoginReqBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message.body; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | import org.lwl.netty.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/9 9 | * @description 登陆消息 10 | */ 11 | 12 | 13 | public class LoginReqBody extends Body{ 14 | 15 | private String userName; 16 | private String password; 17 | 18 | public String getUserName() { 19 | return userName; 20 | } 21 | 22 | public void setUserName(String userName) { 23 | this.userName = userName; 24 | } 25 | 26 | public String getPassword() { 27 | return password; 28 | } 29 | 30 | public void setPassword(String password) { 31 | this.password = password; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | StringBuilder sb = new StringBuilder(); 37 | sb.append("LoginReqBody ["); 38 | sb.append("userName=").append(userName); 39 | sb.append(", password=").append(password).append("]"); 40 | 41 | return sb.toString(); 42 | } 43 | 44 | @Override 45 | public MessageTypeEnum msgType() { 46 | return MessageTypeEnum.LOGIN_REQ; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/body/LoginRespBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message.body; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | import org.lwl.netty.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/9 9 | * @description 登陆消息 10 | */ 11 | 12 | 13 | public class LoginRespBody extends Body{ 14 | 15 | @Override 16 | public String toString() { 17 | StringBuilder sb = new StringBuilder(); 18 | sb.append("LoginRespBody []"); 19 | return sb.toString(); 20 | } 21 | 22 | @Override 23 | public MessageTypeEnum msgType() { 24 | return MessageTypeEnum.LOGIN_RESP; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/body/LogoutBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message.body; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | import org.lwl.netty.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/9 9 | * @description 注销消息,目前没有用到 10 | */ 11 | 12 | 13 | public class LogoutBody extends Body{ 14 | 15 | @Override 16 | public MessageTypeEnum msgType() { 17 | return MessageTypeEnum.LOGOUT; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | StringBuilder sb = new StringBuilder(); 23 | sb.append("LogoutBody []"); 24 | return sb.toString(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/body/ProtocolDataBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message.body; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | import org.lwl.netty.message.Body; 5 | 6 | /** 7 | * @author thinking_fioa 8 | * @createTime 2018/5/26 9 | * @description 协议订阅body,客户端发送该订阅消息 10 | */ 11 | 12 | public class ProtocolDataBody extends Body{ 13 | 14 | /** 15 | * 频道拆分的总发送package数 16 | * 协议定义最大发送4K数据,但考虑到频道内容大于4K,可能多次发送,在接收方再将完整的频道内容拼接完整。 17 | */ 18 | private long pkgSum; 19 | 20 | /** 21 | * 当前发送package序号 22 | */ 23 | private long pkgSequenceNum; 24 | 25 | /** 26 | * package内容长度 27 | */ 28 | private int contentLen; 29 | 30 | /** 31 | * 当前package序号的内容 32 | */ 33 | private byte [] content; 34 | 35 | public long getPkgSum() { 36 | return pkgSum; 37 | } 38 | 39 | public void setPkgSum(long pkgSum) { 40 | this.pkgSum = pkgSum; 41 | } 42 | 43 | public long getPkgSequenceNum() { 44 | return pkgSequenceNum; 45 | } 46 | 47 | public void setPkgSequenceNum(long pkgSequenceNum) { 48 | this.pkgSequenceNum = pkgSequenceNum; 49 | } 50 | 51 | public byte[] getContent() { 52 | return content; 53 | } 54 | 55 | public void setContent(byte[] content) { 56 | this.content = content; 57 | } 58 | 59 | public int getContentLen() { 60 | return contentLen; 61 | } 62 | 63 | public void setContentLen(int contentLen) { 64 | this.contentLen = contentLen; 65 | } 66 | 67 | @Override 68 | public MessageTypeEnum msgType() { 69 | return MessageTypeEnum.PROTOCOL_DATA; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | StringBuilder sb = new StringBuilder(); 75 | sb.append("ProtocolSubBody ["); 76 | sb.append("pkgSum=").append(pkgSum); 77 | sb.append("pkgSequenceNum=").append(pkgSequenceNum); 78 | sb.append("contentLen=").append(contentLen); 79 | if(null != content) { 80 | sb.append("contentLen=").append(content.length).append("]"); 81 | } else { 82 | sb.append("content=").append("null").append("]"); 83 | } 84 | 85 | return sb.toString(); 86 | } 87 | 88 | 89 | } 90 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/message/body/ProtocolSubBody.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.message.body; 2 | 3 | import org.lwl.netty.constant.MessageTypeEnum; 4 | import org.lwl.netty.constant.ProtocolDataType; 5 | import org.lwl.netty.message.Body; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/26 12 | * @description 自定义协议数据消息。服务端根据客户端订阅的类型,发送具体对应的数据 13 | */ 14 | 15 | 16 | public class ProtocolSubBody extends Body{ 17 | 18 | /** 19 | * 订阅的频道类型 20 | */ 21 | private List dataTypeList; 22 | 23 | public List getDataTypeList() { 24 | return dataTypeList; 25 | } 26 | 27 | public void setDataTypeList(List dataTypeList) { 28 | this.dataTypeList = dataTypeList; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | StringBuilder sb = new StringBuilder(); 34 | sb.append("ProtocolSubBody ["); 35 | sb.append("dataTypeList=").append(dataTypeList).append("]"); 36 | 37 | return sb.toString(); 38 | } 39 | 40 | @Override 41 | public MessageTypeEnum msgType() { 42 | return MessageTypeEnum.PROTOCOL_SUB; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/server/ProtobufNettyServer.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.server; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.ChannelInitializer; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 7 | import io.netty.handler.codec.protobuf.ProtobufEncoder; 8 | import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; 9 | import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; 10 | import io.netty.handler.timeout.IdleStateHandler; 11 | import org.lwl.netty.config.ProtocolConfig; 12 | import org.lwl.netty.server.handler.ServerExceptionHandler; 13 | import org.lwl.netty.server.handler.protobuf.HeartbeatServerHandler; 14 | import org.lwl.netty.server.handler.protobuf.LoginRespHandler; 15 | 16 | import java.util.concurrent.TimeUnit; 17 | 18 | /** 19 | * @author thinking_fioa 20 | * @createTime 2018/7/8 21 | * @description 22 | */ 23 | 24 | 25 | public class ProtobufNettyServer extends NettyServer { 26 | 27 | @Override 28 | public void initChannel0(ServerBootstrap bootstrap) { 29 | bootstrap.childHandler(new ProtobufChildChannelHandler()); 30 | } 31 | 32 | private static class ProtobufChildChannelHandler extends ChannelInitializer { 33 | @Override 34 | public void initChannel(SocketChannel ch) throws Exception { 35 | ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); 36 | ch.pipeline().addLast(new ProtobufDecoder(org.lwl.netty.message.protobuf.ProtocolMessage.ProtocolMessageP.getDefaultInstance())); 37 | ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); 38 | ch.pipeline().addLast(new ProtobufEncoder()); 39 | ch.pipeline().addLast(new IdleStateHandler(ProtocolConfig.getHeartbeatInterval(), ProtocolConfig.getHeartbeatInterval(), 0, TimeUnit.SECONDS)); 40 | ch.pipeline().addLast(new LoginRespHandler()); 41 | ch.pipeline().addLast(new HeartbeatServerHandler()); 42 | ch.pipeline().addLast(new ServerExceptionHandler()); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/server/handler/ServerExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.server.handler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/5/26 11 | * @description 处理客户端异常输出 12 | */ 13 | 14 | 15 | public class ServerExceptionHandler extends ChannelInboundHandlerAdapter { 16 | 17 | private static final Logger LOGGER = LogManager.getLogger(ServerExceptionHandler.class); 18 | 19 | @Override 20 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 21 | LOGGER.error("Server Handler happen exception.", cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/server/handler/other/LoginRespHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.server.handler.other; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.client.handler.other.LoginReqHandler; 8 | import org.lwl.netty.config.ProtocolConfig; 9 | import org.lwl.netty.constant.MessageTypeEnum; 10 | import org.lwl.netty.message.ProtocolMessage; 11 | import org.lwl.netty.message.body.LoginReqBody; 12 | import org.lwl.netty.message.body.LoginRespBody; 13 | 14 | /** 15 | * @author thinking_fioa 16 | * @createTime 2018/4/21 17 | * @description 登陆响应的Handler 18 | */ 19 | 20 | 21 | public class LoginRespHandler extends ChannelInboundHandlerAdapter { 22 | private static final Logger LOGGER = LogManager.getLogger(LoginRespHandler.class); 23 | 24 | private static final String USERNAME = ProtocolConfig.getUserName(); 25 | private static final String PASSWORD = ProtocolConfig.getPassword(); 26 | 27 | @Override 28 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 29 | ProtocolMessage message = (ProtocolMessage) msg; 30 | final MessageTypeEnum msgType = message.getHeader().getMsgType(); 31 | if(MessageTypeEnum.LOGIN_REQ.equals(msgType)) { 32 | LOGGER.info("receive login req."); 33 | LoginReqBody reqBody = (LoginReqBody) message.getBody(); 34 | if(checkPermission(reqBody)) { 35 | LOGGER.info("user check pass. login resp sent."); 36 | ctx.writeAndFlush(buildLoginResp()); 37 | } 38 | } else { 39 | ctx.fireChannelRead(msg); 40 | } 41 | } 42 | 43 | private boolean checkPermission(LoginReqBody reqBody) { 44 | final String userName = reqBody.getUserName(); 45 | final String passwd = reqBody.getPassword(); 46 | 47 | return USERNAME.equals(userName) && PASSWORD.equals(passwd); 48 | } 49 | 50 | private ProtocolMessage buildLoginResp() { 51 | LoginRespBody respBody = new LoginRespBody(); 52 | 53 | return ProtocolMessage.createMsgOfEncode(respBody); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/server/handler/other/ProtocolMsgSendHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.server.handler.other; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.client.handler.other.LoginReqHandler; 8 | import org.lwl.netty.constant.MessageTypeEnum; 9 | import org.lwl.netty.message.ProtocolMessage; 10 | import org.lwl.netty.message.body.ProtocolDataBody; 11 | 12 | /** 13 | * @author thinking_fioa 14 | * @createTime 2018/4/21 15 | * @description 发送订阅消息 16 | */ 17 | 18 | public class ProtocolMsgSendHandler extends ChannelInboundHandlerAdapter{ 19 | private static final Logger LOGGER = LogManager.getLogger(ProtocolMsgSendHandler.class); 20 | 21 | @Override 22 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 23 | ProtocolMessage message = (ProtocolMessage) msg; 24 | final MessageTypeEnum msgType = message.getHeader().getMsgType(); 25 | if(MessageTypeEnum.PROTOCOL_SUB.equals(msgType)) { 26 | LOGGER.info("receive msgSub message."); 27 | sendPrtcData(); 28 | } else { 29 | ctx.fireChannelRead(msg); 30 | } 31 | } 32 | 33 | private void sendPrtcData() { 34 | // TODO 提供for循环多次发送,比较各种编码器性能 35 | buildPrctDataMsg(); 36 | } 37 | 38 | private ProtocolMessage buildPrctDataMsg() { 39 | ProtocolDataBody dataBody = new ProtocolDataBody(); 40 | //TODO:: 补充属性 41 | return ProtocolMessage.createMsgOfEncode(dataBody); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/server/handler/protobuf/LoginRespHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.server.handler.protobuf; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.config.ProtocolConfig; 8 | import org.lwl.netty.message.protobuf.*; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/7/15 13 | * @description 14 | */ 15 | 16 | 17 | public class LoginRespHandler extends ChannelInboundHandlerAdapter { 18 | private static final Logger LOGGER = LogManager.getLogger(LoginRespHandler.class); 19 | 20 | private static final String USERNAME = ProtocolConfig.getUserName(); 21 | private static final String PASSWORD = ProtocolConfig.getPassword(); 22 | 23 | @Override 24 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 25 | ProtocolMessage.ProtocolMessageP message = (ProtocolMessage.ProtocolMessageP) msg; 26 | Header.MessageTypeEnum msgType = message.getHeader().getMsgType(); 27 | if(Header.MessageTypeEnum.LOGIN_REQ.equals(msgType)) { 28 | LOGGER.info("receive login req."); 29 | LoginReqBody.LoginReqBodyP loginBody = message.getLoginReqBody(); 30 | if(checkPermission(loginBody)) { 31 | LOGGER.info("user check pass. login resp sent."); 32 | ctx.writeAndFlush(buildLoginResp()); 33 | } 34 | } else { 35 | ctx.fireChannelRead(msg); 36 | } 37 | } 38 | 39 | private boolean checkPermission(LoginReqBody.LoginReqBodyP reqBody) { 40 | final String userName = reqBody.getUserName(); 41 | final String passwd = reqBody.getPassword(); 42 | 43 | return USERNAME.equals(userName) && PASSWORD.equals(passwd); 44 | } 45 | 46 | private ProtocolMessage.ProtocolMessageP buildLoginResp() { 47 | ProtocolMessage.ProtocolMessageP.Builder msgBuilder = ProtocolMessage.ProtocolMessageP.newBuilder(); 48 | // Header 49 | Header.HeaderP.Builder headerBuilder = ProtobufServerCodecHelper.generateHeaderBuilder(Header.MessageTypeEnum.LOGIN_RESP); 50 | msgBuilder.setHeader(headerBuilder); 51 | // Body 52 | LoginRespBody.LoginRespBodyP.Builder loginRespBuilder = LoginRespBody.LoginRespBodyP.newBuilder(); 53 | msgBuilder.setLoginRespBody(loginRespBuilder); 54 | // Tail 55 | Tail.TailP.Builder tailBuilder = ProtobufServerCodecHelper.generateTailBuilder(msgBuilder); 56 | msgBuilder.setTail(tailBuilder); 57 | 58 | return msgBuilder.build(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/server/handler/protobuf/ProtobufServerCodecHelper.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.server.handler.protobuf; 2 | 3 | import org.lwl.netty.message.protobuf.Header; 4 | import org.lwl.netty.message.protobuf.ProtocolMessage; 5 | import org.lwl.netty.message.protobuf.Tail; 6 | import org.lwl.netty.util.CommonUtil; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.concurrent.atomic.AtomicLong; 11 | 12 | /** 13 | * @author thinking_fioa 14 | * @createTime 2018/7/11 15 | * @description 帮助Protobuf编码和解码工具类 16 | */ 17 | 18 | final class ProtobufServerCodecHelper { 19 | 20 | private static final AtomicLong MSG_NUM = new AtomicLong(0); 21 | 22 | private ProtobufServerCodecHelper() { 23 | throw new IllegalAccessError("can not use constructor."); 24 | } 25 | 26 | public static Header.HeaderP.Builder generateHeaderBuilder(Header.MessageTypeEnum msgType) { 27 | Header.HeaderP.Builder headerBuilder = Header.HeaderP.newBuilder(); 28 | 29 | headerBuilder.setMsgNum(MSG_NUM.get()); 30 | headerBuilder.setMsgType(msgType); 31 | headerBuilder.setMsgTime(CommonUtil.nowTime()); 32 | // 下面的值,随机填。主要目的是证明协议支持多种类型格式 33 | headerBuilder.setFlag(2); 34 | headerBuilder.setOneByte(3); 35 | Map attachment = new HashMap<>(); 36 | attachment.put("name", "luweilin"); 37 | attachment.put("age", "20"); 38 | headerBuilder.putAllAttachment(attachment); 39 | 40 | return headerBuilder; 41 | } 42 | 43 | public static Tail.TailP.Builder generateTailBuilder(ProtocolMessage.ProtocolMessageP.Builder msgBuilder) { 44 | byte[] bytes = msgBuilder.build().toByteArray(); 45 | int checkSum = CommonUtil.calCheckSum(bytes); 46 | Tail.TailP.Builder tailBuilder = Tail.TailP.newBuilder(); 47 | tailBuilder.setCheckSum(checkSum); 48 | 49 | return tailBuilder; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/server/handler/protobuf/ProtocolMsgSendHandler.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.server.handler.protobuf; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.lwl.netty.message.protobuf.Header; 8 | import org.lwl.netty.message.protobuf.ProtocolDataBody; 9 | import org.lwl.netty.message.protobuf.ProtocolMessage; 10 | import org.lwl.netty.message.protobuf.Tail; 11 | 12 | /** 13 | * @author thinking_fioa 14 | * @createTime 2018/7/15 15 | * @description 16 | */ 17 | 18 | 19 | public class ProtocolMsgSendHandler extends ChannelInboundHandlerAdapter{ 20 | private static final Logger LOGGER = LogManager.getLogger(ProtocolMsgSendHandler.class); 21 | 22 | @Override 23 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 24 | ProtocolMessage.ProtocolMessageP message = (ProtocolMessage.ProtocolMessageP)msg; 25 | Header.MessageTypeEnum msgType = message.getHeader().getMsgType(); 26 | if(Header.MessageTypeEnum.PROTOCOL_SUB.equals(msgType)) { 27 | LOGGER.info("receive msgSub message."); 28 | sendPrtcData(); 29 | } else { 30 | ctx.fireChannelRead(msg); 31 | } 32 | } 33 | 34 | private void sendPrtcData() { 35 | // TODO 提供for循环多次发送,比较各种编码器性能 36 | } 37 | 38 | private ProtocolMessage.ProtocolMessageP buildPrctDataMsg() { 39 | ProtocolMessage.ProtocolMessageP.Builder msgBuilder = ProtocolMessage.ProtocolMessageP.newBuilder(); 40 | // Header 41 | Header.HeaderP.Builder headerBuilder = ProtobufServerCodecHelper.generateHeaderBuilder(Header.MessageTypeEnum.PROTOCOL_DATA); 42 | msgBuilder.setHeader(headerBuilder); 43 | // Body 44 | ProtocolDataBody.ProtocolDataBodyP.Builder dataBuilder = ProtocolDataBody.ProtocolDataBodyP.newBuilder(); 45 | //TODO: 补充属性 46 | // Tail 47 | Tail.TailP.Builder tailBuilder = Tail.TailP.newBuilder(); 48 | msgBuilder.setTail(tailBuilder); 49 | return msgBuilder.build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /netty-private-protocol/src/main/java/org/lwl/netty/util/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.util; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | 5 | import java.time.LocalDate; 6 | import java.time.LocalDateTime; 7 | import java.time.format.DateTimeFormatter; 8 | 9 | /** 10 | * @author thinking_fioa 11 | * @createTime 2018/5/24 12 | * @description 基础工具静态类 13 | */ 14 | 15 | public final class CommonUtil { 16 | 17 | private CommonUtil() { 18 | throw new IllegalAccessError("can not use constructor about static class"); 19 | } 20 | 21 | /** 22 | * 计算checkSum 23 | * @return 24 | */ 25 | public static int calCheckSum(ByteBuf byteBuf, int length) { 26 | if(length <=0) { 27 | throw new IllegalArgumentException("length <= 0"); 28 | } 29 | byte checkSum = 0; 30 | length = Math.min(length, byteBuf.writerIndex()); 31 | for(int i = 0; i { 19 | new NettyServer().start(); 20 | }).start(); 21 | 22 | new Thread(() -> { 23 | new NettyClientAdapter(new NettyClient()).start(); 24 | }).start(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netty-private-protocol/src/test/java/org/lwl/netty/start/NettyClientStart.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.start; 2 | 3 | import org.lwl.netty.client.NettyClient; 4 | import org.lwl.netty.client.NettyClientAdapter; 5 | import org.lwl.netty.config.ProtocolConfig; 6 | import org.lwl.netty.constant.ProtocolConstant; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * @author thinking_fioa 12 | * @createTime 2018/4/24 13 | * @description 14 | */ 15 | 16 | 17 | public class NettyClientStart { 18 | 19 | public static void main(String [] args) throws IOException { 20 | ProtocolConfig.init(); 21 | new NettyClientAdapter(new NettyClient()).start(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /netty-private-protocol/src/test/java/org/lwl/netty/start/NettyServerStart.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty.start; 2 | 3 | import org.lwl.netty.config.ProtocolConfig; 4 | import org.lwl.netty.server.NettyServer; 5 | 6 | import java.io.IOException; 7 | 8 | /** 9 | * @author thinking_fioa 10 | * @createTime 2018/4/24 11 | * @description 12 | */ 13 | 14 | 15 | public class NettyServerStart { 16 | public static void main(String [] args) throws IOException { 17 | ProtocolConfig.init(); 18 | new NettyServer().start(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /netty-rpc/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkingfioa/netty-learning/739323d31ff2a81879bc0e624606f5562a753541/netty-rpc/README.md -------------------------------------------------------------------------------- /netty-rpc/src/main/java/org/lwl/netty/Test.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/6/14 6 | * @description 7 | */ 8 | 9 | 10 | public class Test { 11 | } 12 | -------------------------------------------------------------------------------- /netty-rpc/src/test/java/org/lwl/netty/Test.java: -------------------------------------------------------------------------------- 1 | package org.lwl.netty; 2 | 3 | /** 4 | * @author thinking_fioa 5 | * @createTime 2018/6/14 6 | * @description 7 | */ 8 | 9 | 10 | public class Test { 11 | } 12 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | thinking-fioa 8 | netty-learning 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | netty-private-protocol 13 | netty-in-action 14 | netty-rpc 15 | netty-practice 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.apache.logging.log4j 23 | log4j-core 24 | 2.10.0 25 | 26 | 27 | org.apache.logging.log4j 28 | log4j-api 29 | 2.10.0 30 | 31 | 32 | com.lmax 33 | disruptor 34 | 3.3.7 35 | 36 | 37 | 38 | io.netty 39 | netty-all 40 | 4.1.22.Final 41 | 42 | 43 | 44 | 45 | --------------------------------------------------------------------------------