netty学习笔记【不断更新】

git 地址:https://github.com/chris1132/netty_lecture
2018-7-20
开始系统学习netty
完成服务端部分
https://blog.csdn.net/u010530712/article/details/82107187

2018-7-22

实现客户端和服务端基于tcp双向通信

源码 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/secondeexample
2018-7-24
1、netty本身不是按照servlet规则;
2、http是请求响应模式的无状态的协议,对于netty是监听tcp的端口号,对于他们底层来说仍是serversocket;
3、对于springmvc程序来说,运行在jetty、Tomcat这些servlet容器上,这些容器保证连接关闭,对于netty,连接可以自己控制如keepalive时间

2018-7-25

1、netty对请求路由没提供支持;

2、netty完成socket相关开发;支持长连接开发;

3、websocket实现客户端与服务端的持续连接,可相互发消息。不需要封装没必要的消息,如http中的header;

2018-7-26
1、SimpleChannelInboundHandler<T> T泛型,要处理的消息的 Java 类型;
2、ChannelHandler,ChannelHandlerContext,ChannelPipeline这三者的关系很特别,相辅相成,一个ChannelPipeline中可以有3多个ChannelHandler实例,而每一个ChannelHandler实例与ChannelPipeline之间的桥梁就是ChannelHandlerContext实例,
ChannelHandlerContext用于获得上下文信息,如获得远程地址。
一个channelPipeline中有多个channelHandler时,且这些channelHandler中有同样的方法时,例如channelActive方法,只会调用处在第一个的channelHandler中的channelActive方法,如果想要调用后续的channelHandler的同名的方法就需要调用以“fire”为开头的方法,如ctx.fireExceptionCaught(cause);

3、EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();

NioEventLoopGroup是用来处理I/O操作的多线程事件循环器,Netty提供了许多不同的EventLoopGroup的实现用来处理不同传输协议。我们实现了一个服务端的应用,会有2个NioEventLoopGroup会被使用。第一个经常被叫做‘boss’,用来接收进来的连接。第二个经常被叫做‘worker’,用来处理已经被接收的连接,一旦‘boss’接收到连接,就会把连接信息注册到‘worker’上。如何知道多少个线程已经被使用,如何映射到已经创建的channel上都需要依赖于EventLoopGroup的实现,并且可以通过构造函数来配置他们的关系。

服务器端 bootstrap.childHandler   客户端:bootstrap.handler
handler针对的是boss发挥作用,处理boss相关信息,如:连接来了后,处理相关日志输出;
childhandler针对worker,boss把连接交给worker后,由childhandler里面对象对worker里面nio线程发挥作用

2018-7-27

netty 多客户端连接与通信 
实现多客户端连接,
需求1:A、B、C-》Server,1、A连接,2、B连接,S打印B连接,S告诉A,B上线,3、C上线,S打印C上线,广播给AB,通知C上线
需求2:ABC都建立连接,A发消息,ABC都受到消息,A显示自己发的消息,BC显示消息来自A

通过handlerAdded,获取添加的channel,使用channelgroup,向channel组里的已有通道广播

源码 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/thirdexample

##netty读写检测机制与长连接要素------心跳

1、手机端和服务器端建立长连接,客户端没退出应用,然后客户端开了飞行模式,则服务器端与客户端无法感知连接已断,相应方法如handlerRemoved方法不会调用。 通过心跳,app向服务器端发心跳包,服务器端收到后,再向app发送ack。如果客户端长时间无法收到反馈消息,则断开

2、IdleStateHandler用来检测空闲状态,设置读写操作有效时间, userEventTriggered 出发某个事件被触发后调用该方法,将事件转发给管道pipeline的下一个handler对象。userEventTriggered 某个事件被触发后调用该方法,将事件转发给管道pipeline的下一个handler对象

源码 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/fourthexample

2018-7-30

netty对websocket的支持

一、websocket解决http存在的问题, 1、http是无状态的,客户端发送两次请求,单从协议本身无法识别两次关系、存了哪些信息,像cookie、session用来解决这些问题, 2、基于请求响应模式的协议,http1.0中请求与响应之前先建立连接,请求发起方是浏览器,响应完成后断开连接,如此反复。HTTP1.1,增加keep-alive,客户端和服务端保持一个短时间的持续连接,这个时间内,客户端与服务端只会建立一个链接,之后的请求复用该连接

二、假长连接,运用轮询的结束,客户端定时发请求,http包含两部分,header和body,header必带,头信息占据的大小远大于内容。

三、websocket实现浏览器与服务器之间的长连接,双方是对等的实体,可以互发信息。长连接在初次建立的时候,客户端向服务端发送请求(包括头信息),之后不用包括头信息,真正发送数据本身

websocket本身是构建在http协议上的升级版协议,客户端向向服务器端发请求建立连接(http连接),header里携带了websocket相关的参数,根据这些参数,服务端通过upgrade这个操作把http连接升级成websocket

websocket是html5规范的一部分

2018-7-31

1、netty 对于处理请求是分块或分段方式,客户端向服务端发送请求,长度1000,netty可能会分成10段,每段会走一个完整的流程,我们自己处理器的channelread0,只读到一段

2、HttpObjectAggregator(len)把分段的请求(响应)聚合成一个完整的请求(响应),len以字节的方式来聚合内容的最大长度,如果聚合的内容超过了长度,调用handleOversizedMessage

3、WebSocketServerProtocolHandler 会处理关于websocket繁重的工作,负责连接握手、以及处理心跳相关的内容,WebSocketServerProtocolHandler("/ws")其中/ws是指websocket uri的地址 如ws://localhost:8899/'ws' WebSocketServerProtocolHandler的ws是指请求地址里的第二个ws

##netty实现服务端和客户端的长连接通信

源码 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/fifthexample
需求,实现网页通过websocket发送数据,服务端收到后反馈消息
在浏览器的ws:/localhost:8899/ws  header中,Status Code:101 Switching Protocols,转换协议  http->ws
在请求头里Request Headers里Upgrade:websocket,虽然访问ws这个请求,但是需要http先去建立连接,建立完成后,再upgrade(升级)到websocket,所以说websocket是在http之上的协议

2018-8-1

##google protobuf使用方式

源码 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/sixthexample
一、protobuf 进行rpc数据传输,用来自定协议,可以更好的、体积更小的对数据编码解码,即序列化反序列化(编码、解码)过程。rpc开发中常用的库
二、RMI:remote method invocation,远程方法调用。(只针对java,client和server都必须是java) 客户端:stub,服务端:skeleton
通过网络传输,A->(调用的对象、方法、参数)序列化成字节码-》网络传输-》B-》接收字节码,反序列化转换成,调用特定对象、方法。
RPC:remote procedure call 远程过程调用  用socket传输
RPC比RMI的优势,跨语言调用,如客户端用python,服务端用java,客户端可以调用自己的一个方法,触发服务端的方法
RPC编写模式,:
1、定义接口说明文件(idl):描述对象、对象成员、接口方法等一系列信息。
2、通过rpc框架所提供的编译器,将接口说明文件编译成具体文件
3、在客户端与服务器端分别引入RPC编译器所生成的文件,即可像调用本地方法一样调用远程方法
决定rpc框架效率看编解码效率
在公司内网中更推荐用rpc方式进行,减少基于http通信带来的损耗。
2018-8-2
使用protocol-buffer构建对象,实现编解码
需求,客户端A,服务器B,A构造对象,发给服务器端,B收到后,打印对象信息,把另一个对象发给A。

用proto文件创建java代码指令,protoc -I=src/protobuf  --java_out=src/main/java src/protobuf/StuffInfo.proto

2018-8-3
接昨天,已完成昨天需求,待解决问题
pipeline.addLast(new ProtobufDecoder(StuffInfo.Teacher.getDefaultInstance()))   //StuffInfo.Teacher编码对象写死,不灵活,

2018-8-6
解决方案,在发送消息外再包一层,见StuffInfo.proto,通过枚举列举各消息类型,再通过一个字段标识本次消息传递的是哪个消息类型
netty基于protocolbuffer这种数据传递过程,对于具体用哪种方法或数据类型来处理请求,存在判断繁杂问题,因为,一段向另一段发送数据时候,接收方要能判断对方发送哪种数据类型,通过if-else去寻找匹配的数据类型
而springmvc和netty相比比,springmvc路径路由很清晰直观,如: @RequestMapping(value="../xx/",method=RequestMethod.GET),下面对于一个处理方法。因为springmvc 有dispatcherServlet(控制器),c向s发起的所有请求,
都经过dispatcherServlet,再分发给不同的controller,springmvc在启动的时候,找到url和方法对应关系,把对应关系保存(如map),s收到请求后,通过url匹配具体方法。

使用Git作为版本控制系统

不建议。。git submodule:  git 仓库里的一个仓库,如netty_lecture是已有的工程,protobuf生成的java代码为protobuf-java工程,通过git submodule把protobuf-java引入到netty_lecture,当protobuf-java本地发生变化,提交远程仓库后,切到netty_lecture目录下,通过git pull,把protobuf-java更新到netty_lecture。问题:分支切换紊乱,A中引入了中间工程B,若在A中对B进行修改,在把B更新到远程仓库,会发生错误

建议。。git subtree

##io、nio回顾 https://blog.csdn.net/u010530712/article/details/82021416

2018-8-27

零拷贝深入剖析及用户空间与内核空间切换方式

猜你喜欢

转载自blog.csdn.net/u010530712/article/details/81187059