netty 解决TCP粘包与拆包问题(二)
TCP以流的方式进行数据传输,上层应用协议为了对消息的区分,采用了以下几种方法。
1.消息固定长度
2.第一篇讲的回车换行符形式
3.以特殊字符作为消息结束符的形式
4.通过消息头中定义长度字段来标识消息的总长度
一、采用指定分割符解决粘包与拆包问题
服务端
package com.ming.netty.nio.stickpack; import java.net.InetSocketAddress; import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; public class EchoServer { public void bind(String addr,int port) throws Exception{
EventLoopGroup bossGroup=new NioEventLoopGroup();
EventLoopGroup workGroup=new NioEventLoopGroup();
try {
ServerBootstrap server=new ServerBootstrap();
server.group(bossGroup,workGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel sc) throws Exception {
ByteBuf delimiter=Unpooled.copiedBuffer("$_".getBytes());//指定消息分割符处理数据
sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));//如果取消了分割符解码,就会出现TCP粘包之类的问题了
sc.pipeline().addLast(new StringDecoder());
sc.pipeline().addLast(new EchoServerHandler()); } });
ChannelFuture f=server.bind(new InetSocketAddress(addr, port)).sync();
System.out.println("启动服务器:"+f.channel().localAddress());
//等等服务器端监听端口关闭
f.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}finally{
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
} public static void main(String[] args) throws Exception{
new EchoServer().bind("192.168.1.108", 8500);
} }
package com.ming.netty.nio.stickpack; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; public class EchoServerHandler extends ChannelHandlerAdapter{ int count=0; @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String body=(String)msg;
System.out.println("服务器收到"+(++count)+"次客户端消息,消息是:"+body);
body+="$_";
ByteBuf rep=Unpooled.copiedBuffer(body.getBytes());
ctx.writeAndFlush(rep);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} }
客服端:
package com.ming.netty.nio.stickpack; import java.net.InetSocketAddress; import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder; public class EchoClient { public void connect(String addr,int port) throws Exception{
EventLoopGroup workGroup=new NioEventLoopGroup();
try {
Bootstrap b=new Bootstrap();
b.group(workGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel sc) throws Exception {
ByteBuf delimiter=Unpooled.copiedBuffer("$_".getBytes());//指定消息分割符
sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
sc.pipeline().addLast(new StringDecoder());
sc.pipeline().addLast(new EchoClientHandler());
} }); ChannelFuture f=b.connect(new InetSocketAddress(addr, port)).sync();
System.out.println("连接服务器:"+f.channel().remoteAddress()+",本地地址:"+f.channel().localAddress());
f.channel().closeFuture().sync();//等待客户端关闭连接 } catch (Exception e) {
e.printStackTrace();
}finally{
workGroup.shutdownGracefully();
}
} public static void main(String[] args) throws Exception{
new EchoClient().connect("192.168.1.108", 8500);
}
}
package com.ming.netty.nio.stickpack; import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; public class EchoClientHandler extends ChannelHandlerAdapter{ int count=0; static final String REQUEST_TEST_DATA="I love you....$_"; @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//发送消息,模拟发送向服务端发送1000条数据
for(int i=0,j=1000;i<j;i++){
ctx.writeAndFlush(Unpooled.copiedBuffer(REQUEST_TEST_DATA.getBytes()));
}
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String sendMsg=(String)msg;
System.out.println("客户端发送给服务器的次数:"+(++count)+",服务器接收数据为:"+sendMsg);
} @Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} }
很多事情看代码解决,hello world!
下篇打算写定长解码了...最后写一下通过消息头中定义长度字段来标识消息的总长度来解码玩玩....
感觉可以点个赞吧,好自恋一把
netty 解决TCP粘包与拆包问题(二)的更多相关文章
- netty 解决TCP粘包与拆包问题(一)
1.什么是TCP粘包与拆包 首先TCP是一个"流"协议,犹如河中水一样连成一片,没有严格的分界线.当我们在发送数据的时候就会出现多发送与少发送问题,也就是TCP粘包与拆包.得不到我 ...
- netty 解决TCP粘包与拆包问题(三)
今天使用netty的固定长度进行解码 固定长度解码的原理就是按照指定消息的长度对消息自动解码. 在netty实现中,只需要采用FiexedLengthFrameDecoder解码器即可... 以下是服 ...
- 【Netty】TCP粘包和拆包
一.前言 前面已经基本上讲解完了Netty的主要内容,现在来学习Netty中的一些可能存在的问题,如TCP粘包和拆包. 二.粘包和拆包 对于TCP协议而言,当底层发送消息和接受消息时,都需要考虑TCP ...
- Netty解决TCP粘包/拆包问题 - 按行分隔字符串解码器
服务端 package org.zln.netty.five.timer; import io.netty.bootstrap.ServerBootstrap; import io.netty.cha ...
- 1. Netty解决Tcp粘包拆包
一. TCP粘包问题 实际发送的消息, 可能会被TCP拆分成很多数据包发送, 也可能把很多消息组合成一个数据包发送 粘包拆包发生的原因 (1) 应用程序一次写的字节大小超过socket发送缓冲区大小 ...
- 【Netty】使用解码器Decoder解决TCP粘包和拆包问题
解码器Decoder和ChannelHandler的关系 netty的解码器通常是继承自ByteToMessageDecoder,而它又是继承自ChannelInboundHandlerAdapter ...
- Netty使用LineBasedFrameDecoder解决TCP粘包/拆包
TCP粘包/拆包 TCP是个”流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TC ...
- 深入学习Netty(5)——Netty是如何解决TCP粘包/拆包问题的?
前言 学习Netty避免不了要去了解TCP粘包/拆包问题,熟悉各个编解码器是如何解决TCP粘包/拆包问题的,同时需要知道TCP粘包/拆包问题是怎么产生的. 在此博文前,可以先学习了解前几篇博文: 深入 ...
- 《精通并发与Netty》学习笔记(13 - 解决TCP粘包拆包(一)概念及实例演示)
一.粘包/拆包概念 TCP是一个“流”协议,所谓流,就是没有界限的一长串二进制数据.TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认 ...
随机推荐
- jQuery基础,定时器,工厂函数
这个星期刚刚学的JQuery,下面我来说说我学的这几个例子 jQuery是JavaScript的一个程序库. Jquery的工厂函数$(): 在Jquery中 $符号等价于jquery,作用是将DOM ...
- html和css的联系
前几天学习了一点html,今天团队为做项目一起学习时,又了解到了新的东西———css,通过组内队员的指导和对一些网站(三翼)的分析,发现了html和css之间联系密切.根据从网上了解的资料,发现htm ...
- 树莓派+移动硬盘搭建NAS服务器
由于树莓派的USB接口不足以给移动硬盘供电,因此需要另外给移动硬盘提供电源. 显示当前已有的存储设备 # fdisk -l Disk /dev/mmcblk0: 7876 MB, 7876902912 ...
- easyui datagrid 编辑模式详解
一,建立编辑器 从api得知,扩展一种新的编辑器类型,需要提供以上几个方法.项目中正好需要一个checkbox 类型编辑器,但在easyui中并没提供这样的编辑器,那我们可以通过扩展编辑器来解决 ...
- 浅谈iOS开发中方法延迟执行的几种方式
Method1. performSelector方法 Method2. NSTimer定时器 Method3. NSThread线程的sleep Method4. GCD 公用延迟执行方法 - (vo ...
- python零碎知识点一
dir(object),列出对象所有可以用的的方法(参数可以为任意对象,例如class,func等) >>>dir('str') ['__add__', '__class__', ' ...
- 【Android测试】UI自动化代码优化之路(临时发布, 随时删除)
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5993622.html 关于UI自动化的抱怨 听过不少人这样 ...
- QStriingList
#include <QCoreApplication> #include<QDebug> #include<QStringList> int main(int ar ...
- Method Swizzling
学习博客: http://www.cocoachina.com/ios/20160121/15076.html (这个作者太牛了,写了我一直想知道的类簇的swizz方法) 一. 一般的swizz 先给 ...
- 如何查看当前使用的Entity Framework版本
Visual Studio 中-----工具-----NuGet套件管理员-----套件管理器控制台-----输入Get-Package即可查看当前使用的版本信息