zoukankan      html  css  js  c++  java
  • 2.Netty的粘包、拆包(一)

    Netty粘包、拆包

    1.什么是拆包、粘包

    (1)拆包、粘包介绍

    TCP是个“流”协议,所谓流,就是没有界限的一串数据。大家可以想想河里的流水,是连成一片的,其间并没有分界线。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

    (2)图解

    (3)代码模拟

    1. 服务端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();
      		}
      	}
      
      }
      
      
    2. 服务端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())+"一个客户端连接!");
      	}
      	
      
      }
      
      
    3. 客户端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();
      		}
      	
      	}
      
      }
      
      
    4. 客户端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())+"  已连接上服务器!");
      	}
      	
      
      }
      
      
    5. 添加依赖

      <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>
      
    6. 预期结果

      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<<<

    7. 实际结果

      (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<<<

  • 相关阅读:
    JQuery源码解析-Dom加载过程
    多个script标签的作用域
    JQuery源码解析-JQuery的工具方法(1)
    JQuery源码解析-JQuery的工具方法
    JQuery源码解析-JQuery.extend()方法
    JQuery源码解析-添加JQuery的一些方法和属性
    中兴捧月算法精英挑战赛-迪杰斯特拉派
    C语言中的内存相关问题
    动态内存管理
    虚函数与虚继承小结
  • 原文地址:https://www.cnblogs.com/TimerHotel/p/netty02.html
Copyright © 2011-2022 走看看