0%

Netty-TCP粘包和拆包及解决方案

TCP粘包和拆包基本介绍

  1. TCP是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样做虽然提高了效率,但是接收端就难于分辨出完整的数据包了,因为面向流的通信是无消息保护边界

  2. 由于TCP无消息保护边界,需要在接收端处理消息边界问题,也就是我们所说的粘包、拆包问题

  3. TCP粘包、拆包图解

    假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况

    1. 服务端分两次读取到了两个独立的数据包,分别D1和D2,没有粘包和拆包
    2. 服务端一次接收到了两个数据包,D1和D2粘合在一起,称为TCP粘包
    3. 服务端分两次读取到了数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到D2包的剩余内容,这称为TCP拆包
    4. 服务端分两次读取到了数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余部分内容D1_2和完整的D2包,也称为TCP拆包
阅读全文 »

Netty-编解码器和handler的调用机制

基本说明

  1. netty的组件设计:Netty的主要组件有Channel、EventLoop、ChannelFuture、ChannelHandler、ChannelPipe等

  2. ChannelHandler充当了处理入站和出站数据的应用程序逻辑的容器。如:实现ChannelInboundHandler接口(或ChannelInboundHandlerAdapter),就可以接收入站事件和数据,这些数据会被业务逻辑处理。当要给客户端发送响应时,也可以从ChannelInboundHandler冲刷数据。业务逻辑通常写在一个或多个ChannelInboundHandler中。ChannelOutboundHandler原理一样,只不过它是用来处理出站数据的

  3. ChannelPipeline提供了ChannelHandler链的容器。以客户端应用程序为例,如果事件的运动方向是从客户端到服务端的,那么称这些事件为出站的,即客户端发送给服务端的数据会通过pipeline中的一系列ChannelOutboundHandler,并被这些Handler处理,反之则称为入站的(从客户端角度判断是出/入站)

    出站要编码,入站要解码

    出站对应写,入站对应读

阅读全文 »

Netty-GoogleProtobuf

编码和解码的基本介绍

  1. 编写网络应用程序时,因为数据在网络中传输的都是二进制字节码数据,在发送数据时就需要编码,接收数据时就需要解码
  2. codec(编解码器)的组成部分有两个:decoder(解码器)和encoder(编码器)。encoder负责把业务数据转换成字节码数据,decoder负责把字节码数据转换成业务数据
阅读全文 »

Netty-应用实例

实例-群聊系统

需求:

  1. 编写一个Netty群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞)
  2. 实现多个群聊
  3. 服务器端:可以监测用户上线、离线,并实现消息转发功能
  4. 客户端:通过channel可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息
阅读全文 »

Netty-核心模块组件

Bootstrap、ServerBootstrap

  1. Bootstrap意思是引导,一个Netty应用通常由一个Bootstrap开始,主要作用是配置整个Netty程序,串联各个组件,Netty中Bootstrap类是客户端程序的启动引导类,ServerBootstrap是服务端启动引导类

  2. 常见的方法有

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // 该方法用于服务器端,用来设置两个EventLoopGroup
    public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup)
    // 该方法用于客户端,用来设置一个EventLoopGroup
    public ServerBootstrap group(EventLoopGroup group)
    // 该方法用来设置一个服务器端的通道实现
    public B channel(Class<? extends C> channelClass)
    // 用来给ServerChannel添加配置
    public <T> B option(ChannelOption<T> option, T value)
    // 用来给接收到的通道添加配置
    public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value)
    // handler对应bossGroup
    public B handler(ChannelHandler handler)
    // 用来设置业务处理类(自定义的handler),对应workerGroup
    public ServerBootstrap childHandler(ChannelHandler childHandler)
    // 用于服务器端,用来设置占用的端口号
    public ChannelFuture bind(int inetPort)
    // 用于客户端,用来连接服务器
    public ChannelFuture connect(String inetHost, int inetPort)
阅读全文 »

Netty-异步模型

基本介绍

  1. 异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的组件在完成后,通过状态、通知和回调来通知调用者。
  2. Netty中的I/O操作是异步的,包括Bind、Write、Connect等操作会简单的返回一个ChannelFuture
  3. 调用者并不能立刻获得结果,而是通过Future-Listener机制,用户可以方便的主动获取或通过通知机制获得IO操作结果
  4. Netty的异步模型是建立在future和callback之上的。callback就是回调。重点说Future,它的核心思想是:假设一个方法fun,计算过程可能非常耗时,等待fun返回显然不合适。那么可以在调用fun的时候,立马返回一个Future,后续可以通过Future去监控方法fun的处理过程(即:Future-Listener机制)
阅读全文 »

Netty-线程模型

线程模型基本介绍

  1. 不同的线程模式,对程序的性能有很大的影响,为了搞情清Netty的线程模式,首先来系统了解各个线程模式,最后再看Netty线程模式有什么优越性
  2. 目前存在的线程模型有:
    • 传统阻塞I/O服务模型
    • Reactor模式
  3. 根据Reactor的数量和处理资源池线程的数量不同,有3种典型的实现
    • 单Reactor单线程
    • 单Reactor多线程
    • 主从Reactor多线程
  4. Netty线程模式(Netty主要基于主从Reactor多线程模型做了一定的改进,其中主从Reactor多线程模型有多个Reactor)
阅读全文 »

Netty-介绍和应用

Netty介绍

  1. Netty是由JBOSS提供的一个Java开源框架,现为GitHub上独立的项目

  2. Netty是一个 异步的、基于事件驱动的网络应用框架,用以快速开发高性能、高可靠性的网络IO程序

  3. Netty主要针对在TCP协议下,面向Clients端的高并发应用,或者Peer-toPeer场景下的大量数据持续传输的应用

  4. Netty本质是一个 NIO框架,适用于服务器通讯相关的多种应用场景

  5. 要透彻理解Netty,需要先学习NIO,这样才能阅读Netty的源码

阅读全文 »

Netty-概述

原生NIO存在的问题

  1. NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等
  2. 需要具备其它的额外技能:要熟悉Java多线程编程,因为NIO编程涉及到Reactor模式,必须对多线程和网络编程非常熟悉
  3. 开发工作量和难度都非常大:例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常流的处理等等
  4. JDK NIO的BUG:例如Epoll Bug,它会导致Selector空轮询,最终导致CPU100%,直到JDK1.7版本该问题仍旧存在,没有被根本解决
阅读全文 »