架构师养成记--20.netty的tcp拆包粘包问题
问题描述
比如要发ABC DEFG HIJK 这一串数据,其中ABC是一个包,DEFG是一个包,HIJK是一个包。由于TCP是基于流发送的,所以有可能出现ABCD EFGH 这种情况,那么ABC和D就粘包了,DEFG被拆开了。
解决方案
1、消息定长,例如报文大小控制为200,如果不够就空位补全
2、在包结尾加特殊字符进行分割,如$_
3、消息分为消息头和消息体,在消息中包含消息长度等字段,然后进行消息逻辑处理。
分隔符方案
服务端
- import java.nio.ByteBuffer;
- 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.FixedLengthFrameDecoder;
- import io.netty.handler.codec.string.StringDecoder;
- import io.netty.handler.codec.string.StringEncoder;
- public class Server {
- public static void main(String[] args) throws Exception{
- //1 创建2个线程,一个是负责接收客户端的连接。一个是负责进行数据传输的
- EventLoopGroup pGroup = new NioEventLoopGroup();
- EventLoopGroup cGroup = new NioEventLoopGroup();
- //2 创建服务器辅助类
- ServerBootstrap b = new ServerBootstrap();
- b.group(pGroup, cGroup)
- .channel(NioServerSocketChannel.class)
- .option(ChannelOption.SO_BACKLOG, 1024)
- .option(ChannelOption.SO_SNDBUF, 32*1024)
- .option(ChannelOption.SO_RCVBUF, 32*1024)
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- protected void initChannel(SocketChannel sc) throws Exception {
- //设置特殊分隔符
- ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
- sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
- //设置字符串形式的解码
- sc.pipeline().addLast(new StringDecoder());
- sc.pipeline().addLast(new ServerHandler());
- }
- });
- //4 绑定连接
- ChannelFuture cf = b.bind(8765).sync();
- //等待服务器监听端口关闭
- cf.channel().closeFuture().sync();
- pGroup.shutdownGracefully();
- cGroup.shutdownGracefully();
- }
- }
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelHandlerAdapter;
- import io.netty.channel.ChannelHandlerContext;
- public class ServerHandler extends ChannelHandlerAdapter {
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- System.out.println(" server channel active... ");
- }
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- String request = (String)msg;
- System.out.println("Server :" + msg);
- String response = "服务器响应:" + msg + "$_";
- ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
- }
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {
- ctx.close();
- }
- }
客户端
- 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.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.FixedLengthFrameDecoder;
- import io.netty.handler.codec.string.StringDecoder;
- import io.netty.handler.codec.string.StringEncoder;
- public class Client {
- public static void main(String[] args) throws Exception {
- EventLoopGroup group = new NioEventLoopGroup();
- Bootstrap b = new Bootstrap();
- b.group(group)
- .channel(NioSocketChannel.class)
- .handler(new ChannelInitializer<SocketChannel>() {
- @Override
- protected void initChannel(SocketChannel sc) throws Exception {
- //
- ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
- sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
- sc.pipeline().addLast(new StringDecoder());
- sc.pipeline().addLast(new ClientHandler());
- }
- });
- ChannelFuture cf = b.connect("127.0.0.1", 8765).sync();
- cf.channel().writeAndFlush(Unpooled.wrappedBuffer("bbbb$_".getBytes()));
- cf.channel().writeAndFlush(Unpooled.wrappedBuffer("cccc$_".getBytes()));
- //等待客户端端口关闭
- cf.channel().closeFuture().sync();
- group.shutdownGracefully();
- }
- }
- import io.netty.channel.ChannelHandlerAdapter;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.util.ReferenceCountUtil;
- public class ClientHandler extends ChannelHandlerAdapter{
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- System.out.println("client channel active... ");
- }
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- try {
- String response = (String)msg;
- System.out.println("Client: " + response);
- } finally {
- ReferenceCountUtil.release(msg);
- }
- }
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- ctx.close();
- }
- }
- import io.netty.channel.ChannelHandlerAdapter;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.util.ReferenceCountUtil;
- public class ClientHandler extends ChannelHandlerAdapter{
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- System.out.println("client channel active... ");
- }
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- try {
- String response = (String)msg;
- System.out.println("Client: " + response);
- } finally {
- ReferenceCountUtil.release(msg);
- }
- }
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- ctx.close();
- }
- }
架构师养成记--20.netty的tcp拆包粘包问题的更多相关文章
- 架构师养成记--19.netty
一.Netty初步 为什么选择Netty? 和NIO比较,要实现一个通信要简单得很多,性能很好.分布式消息中间件.storm.Dubble都是使用Netty作为底层通信. Netty5.0要求jdk1 ...
- 架构师养成记--21.netty编码解码
背景 作为网络传输框架,免不了哟啊传输对象,对象在传输之前就要序列化,这个序列化的过程就是编码过程.接收到编码后的数据就需要解码,还原传输的数据. 代码 工厂类 import io.netty.han ...
- TCP拆包粘包之分隔符解码器
TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...
- tomcat Http11NioProtocol如何解析http请求及如何解决TCP拆包粘包
前言 tomcat是常用的Web 应用服务器,目前国内有很多文章讲解了tomcat架构,请求流程等,但是没有如何解析http请求及如何解决TCP粘包拆包,所以这篇文章的目的就是介绍这块内容,一下内容完 ...
- 使用Netty如何解决拆包粘包的问题
首先,我们通过一个DEMO来模拟TCP的拆包粘包的情况:客户端连续向服务端发送100个相同消息.服务端的代码如下: AtomicLong count = new AtomicLong(0); NioE ...
- 架构师养成记--22.客户端与服务器端保持连接的解决方案,netty的ReadTimeoutHandler
概述 保持客户端与服务器端连接的方案常用的有3种 1.长连接,也就是客户端与服务器端一直保持连接,适用于客户端比较少的情况. 2.定时段连接,比如在某一天的凌晨建立连接,适用于对实时性要求不高的情况. ...
- 架构师养成记--11.Executor概述
常用方法 Executors.newFiexdPool(int nThreads);固定线程数量的线程池: Executors.newSingleThreadExecutor();单个线程的线程池: ...
- 架构师养成记--10.master-worker模式
master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...
- 架构师养成记--3.synchronized细节问题
一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...
随机推荐
- 获取地址栏的URL: PHP JS
1. PHP 获取上一页的URL 在php中可以通过内置的变量的属性来获取上一页的URL: $_SERVER['HTTP_REFERER']. 但是在IE中如果跳转是通过js函数如: window.l ...
- vs与qt
http://blog.csdn.net/woniuye/article/details/54928477 1. #include "qmessagebox.h" QMessage ...
- Java 设计模式系列(十二)代理模式
Java 设计模式系列(十二)代理模式 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. package com.github.binarylei.de ...
- 全球顶尖大学的UX课程资源,英文!
本文由MOCKPLUS团队原创,转载请标明出处,原型设计工具就用更快.更简单的mockplus 要想成为一名优秀的UX设计师,需要掌握很多必备技能.比如,掌握用户体验设计的所有知识和信息架构(易用性方 ...
- POP邮件收取邮件 代码
// 111111.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <WinSock.h> #include ...
- PMP项目管理笔记
项目管理三重制约:时间.成本.范围.结果:质量(结果质量和过程质量)四个层次:复杂事情简单化:分解简单事情量化:临界值量化的事情专业化:规律专业的事情模板化:框架模板 工作分日常运作和项目.日常运作为 ...
- oracle 索引的分类
1. B树索引(默认索引,保存讲过排序过的索引列和对应的rowid值) 1)说明: 1.oracle中最常用的索引:B树索引就是一颗二叉树:叶子节点(双向链表)包含索引列和指向表中每个匹配行的ROWI ...
- 快速排序(Quicksort)的Javascript实现(转载)
日本程序员norahiko,写了一个排序算法的动画演示,非常有趣. 这个周末,我就用它当做教材,好好学习了一下各种排序算法. 排序算法(Sorting algorithm)是计算机科学最古老.最基本的 ...
- Java Web系列:JDBC 基础
ADO.NET在Java中的对应技术是JDBC,企业库DataAccessApplicationBlock模块在Java中的对应是spring-jdbc模块,EntityFramework在Java中 ...
- Cockroachdb 一、系统环境
cockroachdb 一.系统环境 **硬件** 最低标准 a 至少3个节点保证集群可用副本 b 每个节点至少1CPU ,2GB RAM.增加资源配置可支持处理更多的数据,负载,高并发,高性能. 最 ...