# multiprotocal **Repository Path**: stevenworkshop_admin/multiprotocal ## Basic Information - **Project Name**: multiprotocal - **Description**: 采用Netty进行多协议转换为Http,替代原来的Netty-SpringMVC(这个工程是从Netty中启动Spring及MVC的容器)。 本项目,采用Spring容器中启动多个Netty - **Primary Language**: Java - **License**: BSD-2-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-06-08 - **Last Updated**: 2022-11-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # multiprotocal 一、分析协议的基本准备 1、长度信息提取 2、类建模 2.1 准备Request对象,对应协议发送头的属性 准备Body对象的内容,转换为POJO类,多个对象,就新建多个POJO 2.2 准备Response对象,对应协议接收头的属性 准备返回的Body对象,转换为POJO类,多个对象,就新建多个POJO 3、发送包头与url的枚举类或配置文件 4、定义返回的Result 二、具体实现 定义一个协议类,继承ApplicationRunner,绑定端口,设置TCP参数 定义处理链 完整包处理—LengthFiledBasedFrameDecoder的构造函数参数 包头解析— 将数字转换为Request参数 转换为ServletRequest的url,header,body,attribute 继承SpringMVC的prehandle拦截器,将url进行转向匹配 Controller业务处理 返回值编码转换(从SpringMVC的Json序列化的二进制转换为私有协议自定义的序列化方式) 三、服务端主动发送 在客户端第一次发送的时候,验证一下如果通过,放入到ChatSession中。然后服务端持有这个session就可以进行发送。 2022年11月20日 运行MultinettyApplication,ChatServerFromNettyIOT作为Spring的一个Bean,在Spring启动的时候,同时启动,等待客户端接收信息。 服务端是thirdprotocal,该服务端已经支持通过SpringMVC来返回聊天的信息。并且服务端在长连接状态下能主动发起。 客户端需要另外一个项目NettyIoT,在git的另外一个目录上。https://gitee.com/stevenworkshop_admin/nettyIOT.git NettyIOT本身的客户端及服务端是运行正常的,他们采用的方式是自定义的方式,没有采用SpringMVC。 在测试时候,运行NettyIoT的客户端,然后启动本项目的服务端,就可以进行访问.这个是一个比较典型的自定义协议的实现处理方式 2022年11月13日 责任的划分 完整包的接收 包头解码 包头转为url,转为mvc 拦截器处理 根据不同的url,进行body解码,解码后转为json的编码。然后进入MVC的体系 设置VO类,用于接收参数的转换 Controller层进行自动映射 处理业务逻辑 程序正常返回Result 调用发送的返回。 这2个都进入到ResponseEncode中,要求进入的参数为Response。 程序正常返回的类中,在ServerHandle中的最后部分,将mvc的返回值—json序列化的结果,转换为二进制,放入到response的body中。 在主动发送的时候,将Service层中的类,采用objectMapper的方式进行标准序列化后转为body二进制。 在responseEncode中,根据不同的url,进行编码 当前的版本已经能正常与NettyIOT的客户端进行对接。 后续的自己写书的时候, 先介绍一下 自定义的实现方式SpringMVC 但是无法实现的是 url的组合 参数的因素 其他接口的处理 #### 介绍 采用Netty进行多协议转换为Http,替代原来的Netty-SpringMVC(这个工程是从Netty中启动Spring及MVC的容器)。 本项目,采用Spring容器中启动多个Netty # netty 集成 spring mvc 将netty的HttpRequest和HttpResponse对象与servlet的对象进行相互转换。我采用了springtest提供的用来模拟HttpServletRequest和HttpServletResponse的类,这两个类也是它们的子类。 org.springframework.mock.web.MockHttpServletRequest; org.springframework.mock.web.MockHttpServletResponse; #### 项目功能 - 支持spring mvc的controller中,注解方式获取参数 - 支持返回json - 支持post请求 #### 如何测试 - 下载项目,启动org.springframework.sandbox.netty.MyServer - 浏览器访问 http://localhost:8080/hello/foo, 如果返回结果,表示启动成功 #### 如何打包并发布 - 使用maven打包:mvn package - 启动jar:java -jar target/Netty-SpringMVC-1.0.0-SNAPSHOT.jar - 浏览器访问 http://localhost:8080/hello/foo, 如果返回结果,表示启动成功 #### 如何添加自己的业务 - 在org.springframework.sandbox.mvc.TestController中,你可以添加自己的方法 #### 待添加的功能 - 热部署(Hot deployment) - 集群(cluster) #### 版本信息 - 0.0.2 : 集成mybatis - 0.0.1 : 实现netty+springMVC的集成 2019.7.1 更新了StevenTest SpringMVC初始化必须要在Main中执行。执行后每个Socket连接的时候,Channel都必须要被创建。所以Spring的dispacth必须要作为 单例被执行。不需要每次都执行dispatch的初始化 2021.11.15 更新了多协议解析+SpringMVC的部分 客户端采用pro-netty的客户端。通信的包为前面是4个字节+body 在body中,第一个字段为url的路径。 客户端没有任何修改。 服务端,采用NettySpringMVC新建一个文件夹。使用解包的结果转为FullHttpRequest 将其转到后面的SpringMVC的结构。 reference https://www.thinbug.com/q/29071752 https://stackoverflow.com/questions/29071752/how-to-convert-nettys-fullhttprequest-to-httpservletrequest https://github.com/code4craft/netty-servlet/blob/master/src/main/java/us/codecraft/netty_servlet/connector/netty/NettyHttpServletRequestAdaptor.java 这个应该更有效 https://blog.csdn.net/shzy1988/article/details/78841140 目录nettyext是增强版本。 2022年6月6日 复制了一个nettywithesession,追加一个session,客户端仍然采用pro-netty 2022年6月8日 从Spring容器中,无法获取到DispatchServlet。因为DipatchSerlet不是Spring容器中的Bean,所以从getBean是获取不到。 如果采用反射的方式来获取,那么每次都是new一个出来。不是原始的。 所以需要一个新的方法,继承dispatchservlet,自定义一个mydispatchservlet 每个协议单独获取,从工程类中进行获取,每个都可以独立的获取的工厂,是一个对象池。每个协议单独一个dispatchservlet。 这个代码与NettySpringMVC的区别是,这个是从SpringBoot容器中启动的Netty。 Netty-SpringMVC是从Netty中启动Spring容器及MVC Dispatch初始化的时候,有以下内容 MockServletContext servletContext = new MockServletContext(); MockServletConfig servletConfig = new MockServletConfig(servletContext); AnnotationConfigWebApplicationContext wac = new AnnotationConfigWebApplicationContext(); wac.setServletContext(servletContext); wac.setServletConfig(servletConfig); wac.register(AppConfig.class); wac.refresh(); this.dispatcherServlet = new DispatcherServlet(wac); this.dispatcherServlet.init(servletConfig); mydispatch继承与DispatcherServlet,所以具有Dispatch中的各种内容。然后要有一个init的初始化。否则会报错。 客户端仍然是nettybookfromyxx\pro-netty,启动client下的NettyClient 2022年6月8日,版本计划升级为 factory中的线程2个锁的机制来进行处理。 增加一个新的客户协议 增加服务端的Online的Session返回发送的功能。 现在可以参考的例子为 客户端的第一个例子: pro-netty,自定义协议。服务端解码为http,当前的项目 客户端的第二个例子: 聊天的NettyIOT,自定义协议。 客户端的第三个例子, 尼恩的Crazy_tourist_circle_im,自定义协议。 客户端是Websocket_chat_room,尼恩的例子,客户端采用html及js。服务端采用尼恩的Netty的Websocket的服务端。 客户端是自定义协议的netty李林峰的书 调整 把连接发送之后,并不关闭。 先执行pro-netty客户端,发送。然后在Map中有这个channel,然后在调用单独的一个http://localhost:8033/sendback ,在客户端就可以收到信息,并进行记录。 2022年6月10日 已经实现了2种通信协议的客户端传递。 第一种客户端协议, pro-netty,自定义协议。服务端解码为http,当前的项目. 客户端没有修改 服务器采用,自定义解析解析。采用string转码。然后附带session。并且服务端可以发送给登录过的客户端。代码是firstprotocal 第二种客户端协议,客户端是自定义协议的netty李林峰的书 ,12章。 客户端协议没有修改。 服务端采用自定义协议解析,不能用String转码,因为客户端是自己定义的协议。所以服务端必须要采用客户端一样的解码解析。实现了心跳的处理方式。代码是secondprotocal 现在都是通过Controller来进行处理。但是采用Controller返回的类的时候,对Object的处理会按照默认的转换方式。 如果在PipleLine中采用多个handle,在采用Controller的时候的处理方式 如果是只有1个来执行,那么用url来进行映射就可以。每个单独进行返回。 如果是多个每个都执行,那么也可以放在一个controller的方法中,采用if语句或者在Controller中采用责任链的方式来进行执行。 2022年6月13日 head编码与Body编码要分开 如Tomcat解决了Http协议的Head编码,Body编码交给了应用程序来进行处理。对不同种类的ContentType来进行编解码。 Tomcat对Head进行编码,同时对Body中的2个进行编码,一个是text,一个是file。其余的body编码全部交给应用程序来进行处理。springmvc集成了在body中的解码方式。 在web浏览器,它的编码解码方式,也是根据ContentType来决定的,如果是json,那么它的解码就是 增加一个NettyIOT聊天的内容的Server 然后后面需要增加HttpServer WebSocketServer。 这样的协议转换器就比较全了。 2022年6月16日 第三个服务端,对于聊天的chat,nettyiot的,登录的已经好了。 因为它编码是针对每个指令对应的进行编码,不而是采用通用的编码方式。所以,针对每个都要写编码,如loginrequest等。 2022年10月27日 login登录是没有问题,但是在chat的服务的时候,在服务端改造,没有进行完整。 首先碰到的问题, //Optional optionalPlayer = playerJpaRepository.findById(String.valueOf(playerId)); Player player = playerJpaRepository.findByPlayerName(String.valueOf(playerId)).get(0); jpa选择第一个findById的时候,感觉有点奇怪,没有结果。 在chat的服务的时候,dispatch的服务,已经能返回结果。但是在这个publicchat的方法中,它调用了session.write的方法。 所以在这个方法中,有2个与客户端通信的过程 第一个,是mvc返回的结果,要返回。 第二个,是在publicchat的方法中,主动调用session的write的动作 在原始的服务中,也是返回2次 第一次,在publicchat的方法中,返回了message的内容,是消息推送类型 第二次,在正常的response中,返回的data为null。statecode=0,是广播类型。给客户端,客户端转为发送成功的字样。 2022年10月28日 增加来第4个,接入其他种类的协议,是客户端发送的正式的采集的内容