TCP基于链接的协议,并且保证有序性。

但是,每个包的长度,需要明确,否则会发生粘包现象。

以下示例为一个自定义协议的例子,其中包含了拆包的内容。

所有的类:

协议类:

public class PersonProtocol {
private int length;
private byte[] content;
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
}

解码器类:

public class PersonProtocolDecode extends ReplayingDecoder<Void> {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
System.out.println("decode invoke!");
  //拆包的内容如下:先获取长度,再根据获取的长度,获取到包内的内容。
int length = in.readInt();
byte[] content = new byte[length];
  //获取到内容
in.readBytes(content);
PersonProtocol personProtocol = new PersonProtocol();
personProtocol.setLength(length);
personProtocol.setContent(content);
out.add(personProtocol);
}
}

编码器类:

public class PersonProtocolEncode extends MessageToByteEncoder<PersonProtocol>{
@Override
protected void encode(ChannelHandlerContext ctx, PersonProtocol msg, ByteBuf out) throws Exception {
System.out.println("encode invoke!");
out.writeInt(msg.getLength());
out.writeBytes(msg.getContent());
//不需要flush的原因是,此时还是在jvm内部处理代码,并未涉及到io
}
}

服务器处理类:

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.nio.charset.Charset;
import java.util.UUID; public class ServerHandler extends SimpleChannelInboundHandler<PersonProtocol>{
private int count = 0;
@Override
protected void channelRead0(ChannelHandlerContext ctx, PersonProtocol msg) throws Exception {
System.out.println("接收到的消息长度:"+msg.getLength()
+",消息内容: "+new String(msg.getContent(), Charset.forName("utf-8")));
System.out.println("消息的次数:"+ ++count);
PersonProtocol result = new PersonProtocol();
UUID uuid = UUID.randomUUID();
byte[] count = uuid.toString().getBytes(Charset.forName("utf-8"));
System.out.println("发给客户端的数据为:长度"+count.length+",内容:"+uuid );
result.setLength(count.length);
result.setContent(count);
ctx.channel().writeAndFlush(result);
}
}

客户端处理类:

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.nio.charset.Charset; public class ClientHandler extends SimpleChannelInboundHandler<PersonProtocol>{
private int count = 0;
@Override
protected void channelRead0(ChannelHandlerContext ctx, PersonProtocol msg) throws Exception {
System.out.println("接收到的消息长度"+msg.getLength()
+",消息内容: "+new String(msg.getContent(), Charset.forName("utf-8")));
System.out.println("消息的次数:"+ ++count);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
String str = "你好吗?,我很好!,你好吗?我很好!";
for(int i = 0;i < str.split(",").length;i++){
String temp = str.split(",")[i];
System.out.println(temp+",i:"+i);
PersonProtocol pp = new PersonProtocol();
pp.setLength(temp.getBytes(Charset.forName("utf-8")).length);
pp.setContent(temp.getBytes(Charset.forName("utf-8")));
ctx.writeAndFlush(pp);
}
}
}

服务端启动类:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel; public class NettyServer {
public static void main(String[] args) throws Exception{
EventLoopGroup bossGroup = new NioEventLoopGroup(1); //分发事件循环组
EventLoopGroup workGroup = new NioEventLoopGroup();//处理通道事件循环组
ServerBootstrap serverBootstrap = new ServerBootstrap();//初始化服务器
serverBootstrap.group(bossGroup,workGroup) //将两个循环组绑定到服务器
.channel(NioServerSocketChannel.class) //指定通道类型,当前使用NIO模式
.childHandler(new ChannelInitializer<SocketChannel>(){ //指定通道中的过滤器链
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new PersonProtocolDecode()); //解码器过滤
pipeline.addLast(new PersonProtocolEncode());//编码器
pipeline.addLast(new ServerHandler());//具体的业务处理,一般放在最后面
}
});
ChannelFuture channelFuture = serverBootstrap.bind(12345).sync();//绑定到本机的12345端口,等待同步处理结果
channelFuture.channel().closeFuture().sync();//阻塞等待closeFuture的返回,同步等待
bossGroup.shutdownGracefully();//优雅关闭
workGroup.shutdownGracefully();
}
}

客户端启动类:

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; public class NettyClient {
public static void main(String[] args) throws Exception{
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1);
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).
handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new PersonProtocolDecode());
pipeline.addLast(new PersonProtocolEncode());
pipeline.addLast(new ClientHandler());
}
});
ChannelFuture channelFuture = bootstrap.connect("localhost", 12345).sync();
channelFuture.channel().closeFuture().sync();//客户端阻塞,一直运行。
eventLoopGroup.shutdownGracefully();//优雅关闭
}
}

运行服务端,再运行客户端,即可完成测试。

TCP--粘包拆包,netty的解决方式的更多相关文章

  1. TCP粘包/拆包问题的解决

    TCP粘包拆包问题 一个完整的包可能被TCP拆分成多个包,或多个小包封装成一个大的数据包发送. 解决策略 消息定长,如果不够,空位补空格 在包尾增加回车换行符进行分割,例如FTP协议 将消息分为消息头 ...

  2. 第四章 TCP粘包/拆包问题的解决之道---4.1---

    4.1 TCP粘包/拆包 TCP是一个“流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可 ...

  3. 第四章 TCP粘包/拆包问题的解决之道---4.2--- 未考虑TCP粘包导致功能异常案例

    4.2 未考虑TCP粘包导致功能异常案例 如果代码没有考虑粘包/拆包问题,往往会出现解码错位或者错误,导致程序不能正常工作. 4.2.1 TimeServer 的改造 Class : TimeServ ...

  4. Netty使用LineBasedFrameDecoder解决TCP粘包/拆包

    TCP粘包/拆包 TCP是个”流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TC ...

  5. 《精通并发与Netty》学习笔记(13 - 解决TCP粘包拆包(一)概念及实例演示)

    一.粘包/拆包概念 TCP是一个“流”协议,所谓流,就是没有界限的一长串二进制数据.TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认 ...

  6. 深入学习Netty(5)——Netty是如何解决TCP粘包/拆包问题的?

    前言 学习Netty避免不了要去了解TCP粘包/拆包问题,熟悉各个编解码器是如何解决TCP粘包/拆包问题的,同时需要知道TCP粘包/拆包问题是怎么产生的. 在此博文前,可以先学习了解前几篇博文: 深入 ...

  7. Netty(三)TCP粘包拆包处理

    tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. 粘包.拆包问题说明 假设客户端分别发送数据包D1和D ...

  8. Netty(二)——TCP粘包/拆包

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7814644.html 前面讲到:Netty(一)--Netty入门程序 主要内容: TCP粘包/拆包的基础知 ...

  9. TCP粘包/拆包(Netty权威指南)

    无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包/拆包 TCP是个“流”协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是连成一片 ...

  10. TCP粘包/拆包 ByteBuf和channel 如果没有Netty? 传统的多线程服务器,这个也是Apache处理请求的模式

    通俗地讲,Netty 能做什么? - 知乎 https://www.zhihu.com/question/24322387 谢邀.netty是一套在java NIO的基础上封装的便于用户开发网络应用程 ...

随机推荐

  1. vmWare安装centos7之后使用yum安装提示there are on enabled repos(修改yum源)

    可以使用这个命令修改yum源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.rep ...

  2. node依赖包格式区别

    UMD:UMD 版本可以通过 <script> 标签直接用在浏览器中.jsDelivr CDN 的 https://cdn.jsdelivr.net/npm/vue 默认文件就是运行时 + ...

  3. python blob操作

    最近在学习使用Python,操作Oracle数据库采用的是cx_Oracle模块. 对于基本字段,都可以正常操作.但是对于Blob字段,我试试好几次,都没成功.下面贴出测试代码,与大家讨论讨论. 这是 ...

  4. https://zhuanlan.zhihu.com/p/32553477

    科普:QUIC协议原理分析  

  5. AndoridSQLite数据库开发基础教程(8)

    AndoridSQLite数据库开发基础教程(8) 添加索引 索引是一种通过预先排序和对表的一个或多个列构建索引表来优化数据库查找的手段.下面为表添加索引,操作步骤如下: (1)在打开的数据库中,单击 ...

  6. Flutter响应式编程 - Stream

    1.前言 在Dart库中,有两种实现异步编程的方式(Future和Stream),使用它们只需要在代码中引入dart:async即可. 本文主要介绍Stream的相关概念及利用其异步特性来实现简单的响 ...

  7. 开源配置中心xxl-conf的核心原理分析

    XXL-CONF是一款轻量级的开源配置中心项目,由国内大牛许雪里开发.下面是官方对其优点作出的描述: 一个轻量级分布式配置管理平台,拥有"轻量级.秒级动态推送.多环境.跨语言.跨机房.配置监 ...

  8. 代替ESXI的虚拟机解决方案proxmox

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/matengbing/article/de ...

  9. Spring cloud微服务安全实战-3-11API安全机制之登录

    流控.认证.审计.授权以上都做了初步的简单的实现. 之前写的代码,base64加密了用户名和密码. 缺点1:每次请求都要带用户名密码 增加了泄露的风险. 每次传上来用户名和密码都要check验证.ch ...

  10. 戒邪淫利器:《楞严经 四种清净明诲》实例及原经文 (转自学佛网:http://www.xuefo.net/nr/article55/545256.html)

    今日得持首楞严,不读天下糟粕书! 当你读完楞严经后就会很真实的升起这个感觉!根本觉得其他书都是多余的!所以<楞严经>还是要多读,多看!并且<楞严经>戒淫的效果特别好!好好的珍惜 ...