基于Netty的TCP服务框架

19年写的一个基础的TCP服务框架,内置了一个简单IOC容器,当时的目标是一方面能作为组件供第三方集成实现TCP通讯相关功能,另一方面作为提供一种服务框架范式。所以框架核心点主要还是通过适度的封装,隐藏底层的通讯细节,最终调用者接受到的是经过合包分包处理的字节数组,不涉及具体的协议解析,大家如果使用可以再基于业务进行适度的封装。

好,废话不多说,简单介绍下整个架构和源码细节。

Jtcp-cmmon主要放置一些基础配置与工具类。 1、这里注意的服务配置类与默认配置项 JtcpConfig、JtcpOptions,JtcpConfig 顾名思义就是配置类,而JtcpOptions则定义了默认值; 2、RouteEnum枚举中列出了几种通用的网络通讯事件类型,作为注解中的字段定义路由

publicenumRouteEnum{OnConnect,OnDisconnect,OnRecevie,OnSessionTimeOut,OnException}

Jtcp-transport 基于Netty提供了TCP服务与报文解析功能,这里我针对常规固定字节起始的协议,通过递归方式对报文粘包、半包等进行了处理

privatevoidparseCompletePackets(ChannelHandlerContext ctx,byte[] bytesReady,List<Object> out,int magicByteBegin,int magicByteEnd)throwsIOException{if(state ==0){            dataStream =newByteArrayOutputStream();if(bytesReady[0]!= magicByteBegin){return;}            state =1;}if(state >0){intpos= indexOfMagicByte(bytesReady, magicByteEnd);if(state ==2){if(bytesReady[0]== magicByteEnd){                    dataStream.reset();}}if(pos !=-1){                dataStream.write(bytesReady,0, pos);byte[] ad = dataStream.toByteArray();                out.add(ad);                state =0;if(pos != bytesReady.length){byte[] remainBytes =newbyte[bytesReady.length - pos];System.arraycopy(bytesReady, pos, remainBytes,0, remainBytes.length);                    parseCompletePackets(ctx, remainBytes, out, magicByteBegin, magicByteEnd);}}else{                state =2;                dataStream.write(bytesReady,0, bytesReady.length);}}}

自定义实现一个IOC容器,可对消息处理handler进行管理,并通过注解的方式制定消息转发机制 首先遍历main函数下所有class类,并缓存所有指定注解@JtcpComponet的class类对象并注入sproutBeanFactory实例工厂

publicstaticMap<String,Class> getBean(String packageName)throwsException{if(componetMap ==null){Set<Class> clsList = getClasses(packageName);if(clsList ==null|| clsList.isEmpty()){return componetMap;}            componetMap =newHashMap<>(16);for(Class cls : clsList){Annotationannotation= cls.getAnnotation(JtcpComponet.class);if(annotation ==null){continue;}JtcpComponetsproutComponet=(JtcpComponet) annotation;                componetMap.put(sproutComponet.value()==null? cls.getName(): sproutComponet.value(), cls);}}return componetMap;}

实现方法路由,通过@JtcpRoute并结合上面定义链接、断开、消息接收、超时、异常等事件枚举类型,把触发的网络通信事件转发至指定的业务方法中处理

publicvoidinvoke(RouteEnum routeEnum,Object[] args)throwsException{Methodmethod=RouterScanner.getInstance().routeMethod(routeEnum);if(method ==null){return;}Objectbean= applicationContext.getBean(method.getDeclaringClass().getName());if(args ==null){            method.invoke(bean);}else{            method.invoke(bean, args);}}

channelRead接收数据并转发

publicvoidchannelRead(ChannelHandlerContext ctx,Object source){try{byte[] dataBytes =(byte[]) source;JtcpContextsproutContext=newJtcpContext(ctx, dataBytes);RouteMethod.getInstance().invoke(RouteEnum.OnRecevie,newObject[]{ sproutContext });}catch(Exception ex){}}

示例代码

publicstaticvoidmain(String[] args)throwsException{JtcpBootstrapbootstrap=newJtcpBootstrap();        bootstrap.config().setHost("127.0.0.1");        bootstrap.config().setPort(8030);        bootstrap.start();}
publicclassDemoHandler{publicvoidres(JtcpContext jtcpContext){            jtcpContext.context.writeAndFlush(jtcpContext.getRecvBytes());}publicvoidonConnect(JtcpContext context ){System.err.println("连接成功");}}

好的以上就是框架代码的基本构造,涉及到了Netty的应用、粘包半包处理,实例缓存与方法路由等内容,整体并不复杂,这里只是提供了一种服务端编码的思路,供初学者参考。

Original: https://www.cnblogs.com/dafanjoy/p/16653128.html
Author: DaFanJoy
Title: 基于Netty的TCP服务框架

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/714625/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球