netty之粘包分包的处理

  1、netty在进行字节数组传输的时候,会出现粘包和分包的情况。当个数据还好,如果数据量很大。并且不间断的发送给服务器,这个时候就会出现粘包和分包的情况。

  2、简单来说:channelBuffer在接收包的时候,会在当时进行处理,但是当数据量一大,这个时候数据的分隔就不是很明显了。这个时候会出现数据多了或者少了的情况

  3、处理的方式,一般就是编解码。自己定义数据:数据长度+数据。这种简单的方式来实现。在server进行解密操作。

  4、具体的实现过程

  a、客户端进行编码

package com.troy.application.buffer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class Client {

    public static void main(String[] args) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.connect(new InetSocketAddress("localhost",9000));
            //需要发送的数据
            String message = "hello";
            //这里的4代表message的长度所占字节
            ByteBuffer byteBuffer = ByteBuffer.allocate(4+message.length());
            //设置数据
            byteBuffer.putInt(message.length());
            byteBuffer.put(message.getBytes());
            //写出数据
            socketChannel.write(ByteBuffer.wrap(byteBuffer.array()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  b、服务端

package com.troy.application.buffer;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {

    public static void main(String[] args) {

        //声明服务类
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        //设定线程池
        ExecutorService boss = Executors.newCachedThreadPool();
        ExecutorService work = Executors.newCachedThreadPool();

        //设置工厂
        serverBootstrap.setFactory(new NioServerSocketChannelFactory(boss,work));

        //设置管道流
        serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            @Override
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline channelPipeline = Channels.pipeline();
                //添加处理方式
                channelPipeline.addLast("decode",new PackageDecoder());
                channelPipeline.addLast("hello",new HelloHandler());
                return channelPipeline;
            }
        });
        //设置端口
        serverBootstrap.bind(new InetSocketAddress(9000));
    }
}

  c、解码

package com.troy.application.buffer;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;

public class PackageDecoder extends OneToOneDecoder {

    @Override
    protected Object decode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
        ChannelBuffer channelBuffer = (ChannelBuffer) o;
        if (channelBuffer.readableBytes() > 4) {
            //标记读取位置
            channelBuffer.markReaderIndex();
            //读取数据长度
            int n = channelBuffer.readInt();
            if (channelBuffer.readableBytes() < n) {
                //如果数据长度小于设定的数据,则处于缓存状态
                channelBuffer.resetReaderIndex();
                //缓存当前数据,等待数据接入
                return null;
            }
            byte[] bytes = new byte[n];
            channelBuffer.readBytes(bytes);
            return new String(bytes);
        }
        //缓存当前数据,等待数据接入
        return null;
    }
}

  d、数据接收处理

package com.troy.application.buffer;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class HelloHandler extends SimpleChannelHandler{

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {

        System.out.println(e.getMessage());
    }
}
时间: 2024-07-31 07:03:33

netty之粘包分包的处理的相关文章

netty拆包/粘包的解决方案

netty拆包/粘包的解决方案 刚开始学拆包/粘包的时候确实不太好理解,我反复看了几遍就理解了.写下了加深记忆,也希望对大家有所帮助. 本章只介绍简单的二个工具LineBaseFrameDecoder和StringDecoder. 基础知识 1.首先图解拆包/粘包问题出现的原因 假设现在客户端向服务器端发送数据,在某一时间段上客户端分别发送了D1和D2二个数据包给服务器,由于服务器一次读取到的字节数是不确定的,故存在以下5种情况. 情况1:服务器分二次读取到了二个独立的数据包,分别是D1和D2,

服务端NETTY 客户端非NETTY处理粘包和拆包的问题

之前为了调式和方便一直没有处理粘包的问题,今天专门花了时间来搞NETTY的粘包处理,要知道在高并发下,不处理粘包是不可能的,数据流的混乱会造成业务的崩溃什么的我就不说了.所以这个问题 在我心里一直是个结. 使用NETTY真的很幸福,以前用C写服务端 还的自己处理粘包的问题 各种痛苦 不过那也是基本功 没办法的事情.在NETTY里面 有几个拆个包器 我使用的是 LengthFileldBasedFrameDecoder,这个用来解析带有长度属性的包,只要我们在传输协议中加入包的总长度就行 arg0

【游戏开发】Netty TCP粘包/拆包问题的解决办法(二)

上一篇:[Netty4.X]Unity客户端与Netty服务器的网络通信(一) 一.什么是TCP粘包/拆包 如图所示,假如客户端分别发送两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4中情况: 第一种情况:Server端分别读取到D1和D2,没有产生粘包和拆包的情况. 第二种情况:Server端一次接收到两个数据包,D1和D2粘合在一起,被称为TCP粘包. 第三种情况:Server端分2次读取到2个数据包,第一次读取到D1包和D2包的部分内容D2_1,第二次

2.Netty的粘包、拆包(一)

Netty粘包.拆包 1.什么是拆包.粘包 (1)拆包.粘包介绍 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是连成一片的,其间并没有分界线.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. (2)图解 (3)代码模拟 服务端Server package com.xm.n

3.Netty的粘包、拆包(二)

Netty提供的TCP数据拆包.粘包解决方案 1.前言 关于TCP的数据拆包.粘包的介绍,我在上一篇文章里面已经有过介绍. 想要了解一下的,请点击这里 Chick Here! 今天我们要讲解的是Netty提供的两种解决方案: DelimiterBasedFrameDecoder FixedLengthFrameDecoder 2.关于Decoder 先观察下两段代码的不同 (1)使用StringDecoder之前 @Override public void channelRead(Channel

Netty解决粘包和拆包问题的四种方案

在RPC框架中,粘包和拆包问题是必须解决一个问题,因为RPC框架中,各个微服务相互之间都是维系了一个TCP长连接,比如dubbo就是一个全双工的长连接.由于微服务往对方发送信息的时候,所有的请求都是使用的同一个连接,这样就会产生粘包和拆包的问题.本文首先会对粘包和拆包问题进行描述,然后介绍其常用的解决方案,最后会对Netty提供的几种解决方案进行讲解.这里说明一下,由于oschina将"jie ma qi"认定为敏感文字,因而本文统一使用"解码一器"表示该含义 粘包

Netty中粘包和拆包的解决方案

粘包和拆包是TCP网络编程中不可避免的,无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包和拆包 TCP是个“流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. 如图所示,假设客户端分别发送了两个数据包D1和D2给服务端,

libevent粘包分包解决方案:bufferevent + evbuffer

转自:http://blog.sina.com.cn/s/blog_9f1496990102vshz.html 原文:http://www.lvtao.net/c/631.html Libevent介绍 libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制.著名分布式缓存软件memcached也是libevent based,而且libevent在使用上可以做到跨平台,而且根据libeve

解决粘包问题

粘包分包问题 # 如果使用异步方式 beginreceive() 如果开辟的数组足够大,是不会产生分包发送的问题,但是- - 足够大是多大-. 上一篇写了Socket通讯,这一篇整理一下粘包分包的问题, 主要思路是在字节数据前四个位置保存一个数据的长度后边保存数据,通过一个类进行存储传输过来的数据,再使用这个类进行解析. 服务器 namespace 服务器 { //解析类 class Message { private byte[] date = new byte[10240]; public