2.Netty的粘包、拆包(一)
Netty粘包、拆包
1.什么是拆包、粘包
(1)拆包、粘包介绍
TCP是个“流”协议,所谓流,就是没有界限的一串数据。大家可以想想河里的流水,是连成一片的,其间并没有分界线。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。
(2)图解
(3)代码模拟
服务端Server
package com.xm.netty.demo02; import java.net.InetSocketAddress; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel; public class Server { private final int port; public Server(int port) {
this.port = port;
} public static void main(String[] args) { int port = 8989;
try {
new Server(port).start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } private void start() throws InterruptedException {
EventLoopGroup g1 = new NioEventLoopGroup();
EventLoopGroup g2 = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(g1,g2)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress( port))
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new ServerHandler());
}
});
ChannelFuture future = bootstrap.bind().sync();
future.channel().closeFuture().sync();
} finally {
g1.shutdownGracefully().sync();
g2.shutdownGracefully().sync();
}
} }服务端ServerHandler
package com.xm.netty.demo02; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil; public class ServerHandler extends ChannelHandlerAdapter { @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf in = (ByteBuf) msg;
String str = in.toString(CharsetUtil.UTF_8);
System.out.println("Server:"+str);
str = "服务器返回--->"+ str;
ctx.writeAndFlush(Unpooled.copiedBuffer(str.getBytes()));
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())+"一个客户端连接!");
} }客户端Client
package com.xm.netty.demo02; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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 Client { private final int port;
private final String host; public Client(int port, String host) {
this.port = port;
this.host = host;
} public static void main(String[] args) {
String host = "127.0.0.1";
int port = 8989;
try {
new Client(port, host).start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} private void start() throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap
.group(group)
.channel(NioSocketChannel.class)
.remoteAddress(host, port)
.handler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientHandler());
} }); ChannelFuture future = bootstrap.connect().sync(); for(int i=10;i<20;i++) {
String str = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now()) + "---- " +i+"<<<";
future.channel().writeAndFlush(Unpooled.copiedBuffer(str.getBytes()));
} future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
} } }客户端ClientHandler
package com.xm.netty.demo02; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelHandlerAdapter { @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { ByteBuf in = (ByteBuf) msg;
String str = in.toString(CharsetUtil.UTF_8);
System.out.println("Client:"+str); } finally {
ReferenceCountUtil.release(msg);
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())+" 已连接上服务器!");
} }添加依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xm</groupId>
<artifactId>netty</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
</dependencies>
</project>
预期结果
1)服务器
2018-10-11T18:37:19.857一个客户端连接!
Server:2018-10-11T18:37:19.855---- 10<<<
Server:2018-10-11T18:37:20.377---- 11<<<
Server:2018-10-11T18:37:20.877---- 12<<<
Server:2018-10-11T18:37:21.378---- 13<<<
Server:2018-10-11T18:37:21.879---- 14<<<
Server:2018-10-11T18:37:22.379---- 15<<<
Server:2018-10-11T18:37:22.879---- 16<<<
Server:2018-10-11T18:37:23.38---- 17<<<
Server:2018-10-11T18:37:23.881---- 18<<<
Server:2018-10-11T18:37:24.382---- 19<<<
(2)客户端
2018-10-11T18:37:19.855 已连接上服务器!
Client:服务器返回--->2018-10-11T18:37:19.855---- 10<<<
Client:服务器返回--->2018-10-11T18:37:20.377---- 11<<<
Client:服务器返回--->2018-10-11T18:37:20.877---- 12<<<
Client:服务器返回--->2018-10-11T18:37:21.378---- 13<<<
Client:服务器返回--->2018-10-11T18:37:21.879---- 14<<<
Client:服务器返回--->2018-10-11T18:37:22.379---- 15<<<
Client:服务器返回--->2018-10-11T18:37:22.879---- 16<<<
Client:服务器返回--->2018-10-11T18:37:23.38---- 17<<<
Client:服务器返回--->2018-10-11T18:37:23.881---- 18<<<
Client:服务器返回--->2018-10-11T18:37:24.382---- 19<<<
实际结果
(1)服务器
2018-10-11T18:35:40.988一个客户端连接!
Server:2018-10-11T18:35:40.986---- 10<<<2018-10-11T18:35:41.01---- 11<<<2018-10-11T18:35:41.01---- 12<<<2018-10-11T18:35:41.01---- 13<<<2018-10-11T18:35:41.01---- 14<<<2018-10-11T18:35:41.01---- 15<<<2018-10-11T18:35:41.01---- 16<<<2018-10-11T18:35:41.01---- 17<<<2018-10-11T18:35:41.01---- 18<<<2018-10-11T18:35:41.01---- 19<<<(2)客户端
2018-10-11T18:35:40.986 已连接上服务器!
Client:服务器返回--->2018-10-11T18:35:40.986---- 10<<<2018-10-11T18:35:41.01---- 11<<<2018-10-11T18:35:41.01---- 12<<<2018-10-11T18:35:41.01---- 13<<<2018-10-11T18:35:41.01---- 14<<<2018-10-11T18:35:41.01---- 15<<<2018-10-11T18:35:41.01---- 16<<<2018-10-11T18:35:41.01---- 17<<<2018-10-11T18:35:41.01---- 18<<<2018-10-11T18:35:41.01---- 19<<<
2.Netty的粘包、拆包(一)的更多相关文章
- netty 解决粘包拆包问题
netty server TimeServer package com.zhaowb.netty.ch4_3; import io.netty.bootstrap.ServerBootstrap; i ...
- Netty TCP粘包/拆包问题《二》
1.DelimiterBasedFrameDecoder:是以分隔符作为结束标志进行解决粘包/拆包问题 代码: EchoClient:客户端 /* * Copyright 2012 The Netty ...
- Netty TCP粘包/拆包问题《一》
1.使用LineBasedFrameDecoder,StringDecoder解析器进行解决TCP粘包/拆包问题 2.代码搞起: TimeClient:客户端 /* * Copyright 2013- ...
- netty: 解决粘包拆包: 分隔符DelimiterBasedFrameDecoder,定长消息FixedLengthFrameDecoder
DelimiterBasedFrameDecoder 自定义分隔符 给Server发送多条信息,但是server会讲多条信息合并为一条.这时候我们需要对发生的消息指定分割,让client和server ...
- Netty入门系列(2) --使用Netty解决粘包和拆包问题
前言 上一篇我们介绍了如果使用Netty来开发一个简单的服务端和客户端,接下来我们来讨论如何使用解码器来解决TCP的粘包和拆包问题 TCP为什么会粘包/拆包 我们知道,TCP是以一种流的方式来进行网络 ...
- Netty(三)TCP粘包拆包处理
tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. 粘包.拆包问题说明 假设客户端分别发送数据包D1和D ...
- 1. Netty解决Tcp粘包拆包
一. TCP粘包问题 实际发送的消息, 可能会被TCP拆分成很多数据包发送, 也可能把很多消息组合成一个数据包发送 粘包拆包发生的原因 (1) 应用程序一次写的字节大小超过socket发送缓冲区大小 ...
- Netty(二)——TCP粘包/拆包
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7814644.html 前面讲到:Netty(一)--Netty入门程序 主要内容: TCP粘包/拆包的基础知 ...
- Netty解决粘包和拆包问题的四种方案
在RPC框架中,粘包和拆包问题是必须解决一个问题,因为RPC框架中,各个微服务相互之间都是维系了一个TCP长连接,比如dubbo就是一个全双工的长连接.由于微服务往对方发送信息的时候,所有的请求都是使 ...
- Netty 粘包 & 拆包 & 编码 & 解码 & 序列化 介绍
目录: 粘包 & 拆包及解决方案 ByteToMessageDecoder 基于长度编解码器 基于分割符的编解码器 google 的 Protobuf 序列化介绍 其他的 前言 Netty 作 ...
随机推荐
- RedHat6.5安装MySQL5.7
安装环境:RedHat6.5 第一步:下载 下载MySQL5.7:http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.12-1.el6.x8 ...
- python 合并重叠数据
- vue中遇到的坑
如何解决在vue中替换图片.一个使用base64,而我们使用zepto之后,src找不到资源,因为已经打包了,难道强行写base64. 1. 引入文件时语法很重要! import "Foot ...
- CentOS 使用RPM方式安装MySQL5.6
转载自:http://blog.csdn.net/liumm0000/article/details/18841197 RPM方式安装MySQL5.6 a. 检查MySQL及相关RPM包,是否安装,如 ...
- MySQL查询上个月数据
SELECT * FROM order o WHERE o.payTime BETWEEN DATE_FORMAT(DATE_ADD(NOW(),INTERVAL MONTH),'%Y-%m-01') ...
- MySQL的btree索引和hash索引
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...
- 小程序封装一个ajax
小程序中,我们一般习惯把提交接口请求的方法放在一个公共js里面.下面是一个简单实现. (1)我们把所有请求的地址都放在一个json里面 var postAddress = { "domin& ...
- Dictionary and KeyValuePair.
简单一句话: Dictionary 是 由 KeyValuePair结构 组成的集合 The Dictionary<TKey, TValue>.Enumerator.Current pro ...
- MySQL累加值时,考虑到值有为NULL的情况.
一个字段,表示报名人数,默认为null,经考虑,以以下sql执行加1: ) where id='xxx'
- Android开发基础
一.Android开发环境搭建 1.下载安卓SDK 官方下载地址:http://developer.android.com/sdk/index.html 2.下载安装JDK 官方下载地址:JDK6 h ...