问题描述

比如要发ABC DEFG HIJK 这一串数据,其中ABC是一个包,DEFG是一个包,HIJK是一个包。由于TCP是基于流发送的,所以有可能出现ABCD EFGH 这种情况,那么ABC和D就粘包了,DEFG被拆开了。

解决方案

1、消息定长,例如报文大小控制为200,如果不够就空位补全

2、在包结尾加特殊字符进行分割,如$_

3、消息分为消息头和消息体,在消息中包含消息长度等字段,然后进行消息逻辑处理。

分隔符方案

服务端

  1. import java.nio.ByteBuffer;
  2.  
  3. import io.netty.bootstrap.ServerBootstrap;
  4. import io.netty.buffer.ByteBuf;
  5. import io.netty.buffer.Unpooled;
  6. import io.netty.channel.ChannelFuture;
  7. import io.netty.channel.ChannelInitializer;
  8. import io.netty.channel.ChannelOption;
  9. import io.netty.channel.EventLoopGroup;
  10. import io.netty.channel.nio.NioEventLoopGroup;
  11. import io.netty.channel.socket.SocketChannel;
  12. import io.netty.channel.socket.nio.NioServerSocketChannel;
  13. import io.netty.handler.codec.DelimiterBasedFrameDecoder;
  14. import io.netty.handler.codec.FixedLengthFrameDecoder;
  15. import io.netty.handler.codec.string.StringDecoder;
  16. import io.netty.handler.codec.string.StringEncoder;
  17.  
  18. public class Server {
  19.  
  20. public static void main(String[] args) throws Exception{
  21. //1 创建2个线程,一个是负责接收客户端的连接。一个是负责进行数据传输的
  22. EventLoopGroup pGroup = new NioEventLoopGroup();
  23. EventLoopGroup cGroup = new NioEventLoopGroup();
  24.  
  25. //2 创建服务器辅助类
  26. ServerBootstrap b = new ServerBootstrap();
  27. b.group(pGroup, cGroup)
  28. .channel(NioServerSocketChannel.class)
  29. .option(ChannelOption.SO_BACKLOG, 1024)
  30. .option(ChannelOption.SO_SNDBUF, 32*1024)
  31. .option(ChannelOption.SO_RCVBUF, 32*1024)
  32. .childHandler(new ChannelInitializer<SocketChannel>() {
  33. @Override
  34. protected void initChannel(SocketChannel sc) throws Exception {
  35. //设置特殊分隔符
  36. ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
  37. sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
  38. //设置字符串形式的解码
  39. sc.pipeline().addLast(new StringDecoder());
  40. sc.pipeline().addLast(new ServerHandler());
  41. }
  42. });
  43.  
  44. //4 绑定连接
  45. ChannelFuture cf = b.bind(8765).sync();
  46.  
  47. //等待服务器监听端口关闭
  48. cf.channel().closeFuture().sync();
  49. pGroup.shutdownGracefully();
  50. cGroup.shutdownGracefully();
  51.  
  52. }
  53.  
  54. }
  1. import io.netty.buffer.Unpooled;
  2. import io.netty.channel.ChannelHandlerAdapter;
  3. import io.netty.channel.ChannelHandlerContext;
  4.  
  5. public class ServerHandler extends ChannelHandlerAdapter {
  6.  
  7. @Override
  8. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  9. System.out.println(" server channel active... ");
  10. }
  11.  
  12. @Override
  13. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  14. String request = (String)msg;
  15. System.out.println("Server :" + msg);
  16. String response = "服务器响应:" + msg + "$_";
  17. ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
  18. }
  19.  
  20. @Override
  21. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  22.  
  23. }
  24.  
  25. @Override
  26. public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {
  27. ctx.close();
  28. }
  29.  
  30. }

客户端

  1. import io.netty.bootstrap.Bootstrap;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.buffer.Unpooled;
  4. import io.netty.channel.ChannelFuture;
  5. import io.netty.channel.ChannelInitializer;
  6. import io.netty.channel.EventLoopGroup;
  7. import io.netty.channel.nio.NioEventLoopGroup;
  8. import io.netty.channel.socket.SocketChannel;
  9. import io.netty.channel.socket.nio.NioSocketChannel;
  10. import io.netty.handler.codec.DelimiterBasedFrameDecoder;
  11. import io.netty.handler.codec.FixedLengthFrameDecoder;
  12. import io.netty.handler.codec.string.StringDecoder;
  13. import io.netty.handler.codec.string.StringEncoder;
  14.  
  15. public class Client {
  16.  
  17. public static void main(String[] args) throws Exception {
  18.  
  19. EventLoopGroup group = new NioEventLoopGroup();
  20.  
  21. Bootstrap b = new Bootstrap();
  22. b.group(group)
  23. .channel(NioSocketChannel.class)
  24. .handler(new ChannelInitializer<SocketChannel>() {
  25. @Override
  26. protected void initChannel(SocketChannel sc) throws Exception {
  27. //
  28. ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
  29. sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
  30. sc.pipeline().addLast(new StringDecoder());
  31. sc.pipeline().addLast(new ClientHandler());
  32. }
  33. });
  34.  
  35. ChannelFuture cf = b.connect("127.0.0.1", 8765).sync();
  36.  
  37. cf.channel().writeAndFlush(Unpooled.wrappedBuffer("bbbb$_".getBytes()));
  38. cf.channel().writeAndFlush(Unpooled.wrappedBuffer("cccc$_".getBytes()));
  39.  
  40. //等待客户端端口关闭
  41. cf.channel().closeFuture().sync();
  42. group.shutdownGracefully();
  43.  
  44. }
  45. }
  1. import io.netty.channel.ChannelHandlerAdapter;
  2. import io.netty.channel.ChannelHandlerContext;
  3. import io.netty.util.ReferenceCountUtil;
  4.  
  5. public class ClientHandler extends ChannelHandlerAdapter{
  6.  
  7. @Override
  8. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  9. System.out.println("client channel active... ");
  10. }
  11.  
  12. @Override
  13. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  14. try {
  15. String response = (String)msg;
  16. System.out.println("Client: " + response);
  17. } finally {
  18. ReferenceCountUtil.release(msg);
  19. }
  20. }
  21.  
  22. @Override
  23. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  24. }
  25.  
  26. @Override
  27. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  28. ctx.close();
  29. }
  30.  
  31. }
  1. import io.netty.channel.ChannelHandlerAdapter;
  2. import io.netty.channel.ChannelHandlerContext;
  3. import io.netty.util.ReferenceCountUtil;
  4.  
  5. public class ClientHandler extends ChannelHandlerAdapter{
  6.  
  7. @Override
  8. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  9. System.out.println("client channel active... ");
  10. }
  11.  
  12. @Override
  13. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  14. try {
  15. String response = (String)msg;
  16. System.out.println("Client: " + response);
  17. } finally {
  18. ReferenceCountUtil.release(msg);
  19. }
  20. }
  21.  
  22. @Override
  23. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  24. }
  25.  
  26. @Override
  27. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  28. ctx.close();
  29. }
  30.  
  31. }

架构师养成记--20.netty的tcp拆包粘包问题的更多相关文章

  1. 架构师养成记--19.netty

    一.Netty初步 为什么选择Netty? 和NIO比较,要实现一个通信要简单得很多,性能很好.分布式消息中间件.storm.Dubble都是使用Netty作为底层通信. Netty5.0要求jdk1 ...

  2. 架构师养成记--21.netty编码解码

    背景 作为网络传输框架,免不了哟啊传输对象,对象在传输之前就要序列化,这个序列化的过程就是编码过程.接收到编码后的数据就需要解码,还原传输的数据. 代码 工厂类 import io.netty.han ...

  3. TCP拆包粘包之分隔符解码器

    TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...

  4. tomcat Http11NioProtocol如何解析http请求及如何解决TCP拆包粘包

    前言 tomcat是常用的Web 应用服务器,目前国内有很多文章讲解了tomcat架构,请求流程等,但是没有如何解析http请求及如何解决TCP粘包拆包,所以这篇文章的目的就是介绍这块内容,一下内容完 ...

  5. 使用Netty如何解决拆包粘包的问题

    首先,我们通过一个DEMO来模拟TCP的拆包粘包的情况:客户端连续向服务端发送100个相同消息.服务端的代码如下: AtomicLong count = new AtomicLong(0); NioE ...

  6. 架构师养成记--22.客户端与服务器端保持连接的解决方案,netty的ReadTimeoutHandler

    概述 保持客户端与服务器端连接的方案常用的有3种 1.长连接,也就是客户端与服务器端一直保持连接,适用于客户端比较少的情况. 2.定时段连接,比如在某一天的凌晨建立连接,适用于对实时性要求不高的情况. ...

  7. 架构师养成记--11.Executor概述

    常用方法 Executors.newFiexdPool(int nThreads);固定线程数量的线程池: Executors.newSingleThreadExecutor();单个线程的线程池: ...

  8. 架构师养成记--10.master-worker模式

    master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...

  9. 架构师养成记--3.synchronized细节问题

    一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...

随机推荐

  1. 获取地址栏的URL: PHP JS

    1. PHP 获取上一页的URL 在php中可以通过内置的变量的属性来获取上一页的URL: $_SERVER['HTTP_REFERER']. 但是在IE中如果跳转是通过js函数如: window.l ...

  2. vs与qt

    http://blog.csdn.net/woniuye/article/details/54928477 1. #include "qmessagebox.h" QMessage ...

  3. Java 设计模式系列(十二)代理模式

    Java 设计模式系列(十二)代理模式 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. package com.github.binarylei.de ...

  4. 全球顶尖大学的UX课程资源,英文!

    本文由MOCKPLUS团队原创,转载请标明出处,原型设计工具就用更快.更简单的mockplus 要想成为一名优秀的UX设计师,需要掌握很多必备技能.比如,掌握用户体验设计的所有知识和信息架构(易用性方 ...

  5. POP邮件收取邮件 代码

    // 111111.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <WinSock.h> #include ...

  6. PMP项目管理笔记

    项目管理三重制约:时间.成本.范围.结果:质量(结果质量和过程质量)四个层次:复杂事情简单化:分解简单事情量化:临界值量化的事情专业化:规律专业的事情模板化:框架模板 工作分日常运作和项目.日常运作为 ...

  7. oracle 索引的分类

    1. B树索引(默认索引,保存讲过排序过的索引列和对应的rowid值) 1)说明: 1.oracle中最常用的索引:B树索引就是一颗二叉树:叶子节点(双向链表)包含索引列和指向表中每个匹配行的ROWI ...

  8. 快速排序(Quicksort)的Javascript实现(转载)

    日本程序员norahiko,写了一个排序算法的动画演示,非常有趣. 这个周末,我就用它当做教材,好好学习了一下各种排序算法. 排序算法(Sorting algorithm)是计算机科学最古老.最基本的 ...

  9. Java Web系列:JDBC 基础

    ADO.NET在Java中的对应技术是JDBC,企业库DataAccessApplicationBlock模块在Java中的对应是spring-jdbc模块,EntityFramework在Java中 ...

  10. Cockroachdb 一、系统环境

    cockroachdb 一.系统环境 **硬件** 最低标准 a 至少3个节点保证集群可用副本 b 每个节点至少1CPU ,2GB RAM.增加资源配置可支持处理更多的数据,负载,高并发,高性能. 最 ...