netty9---使用编码解码器

客户端:

package com.client;

import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
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.NioClientSocketChannelFactory;
import com.cn.codc.RequestEncoder;
import com.cn.codc.ResponseDecoder;
import com.cn.model.Request;
import com.cn.module.fuben.request.FightRequest;
/**
 * netty客户端入门
 */
public class Client {

    public static void main(String[] args) throws InterruptedException {
        
        //服务类
        ClientBootstrap bootstrap = new  ClientBootstrap();
        
        //线程池
        ExecutorService boss = Executors.newCachedThreadPool();
        ExecutorService worker = Executors.newCachedThreadPool();
        
        //socket工厂
        bootstrap.setFactory(new NioClientSocketChannelFactory(boss, worker));
        
        //管道工厂
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            
            @Override
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("decoder", new ResponseDecoder());//Response解码器
                pipeline.addLast("encoder", new RequestEncoder());//Request编码器
                pipeline.addLast("hiHandler", new HiHandler());//通过ResponseDecoder解码的是一个Response对象。
                return pipeline;
            }
        });
        
        //连接服务端
        ChannelFuture connect = bootstrap.connect(new InetSocketAddress("127.0.0.1", 10101));
        Channel channel = connect.sync().getChannel();
        
        System.out.println("client start");
        
        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("请输入");
            int fubenId = Integer.parseInt(scanner.nextLine());
            int count = Integer.parseInt(scanner.nextLine());
            
            FightRequest fightRequest = new FightRequest();
            fightRequest.setFubenId(fubenId);
            fightRequest.setCount(count);
            
            Request request = new Request();
            request.setModule((short) 1);//请求第一个模块的
            request.setCmd((short) 1);
            request.setData(fightRequest.getBytes());//fightRequest是数据体data
            //发送请求
            channel.write(request);
        }
    }

}
package com.client;

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

import com.cn.model.Response;
import com.cn.model.StateCode;
import com.cn.module.fuben.request.FightRequest;
import com.cn.module.fuben.response.FightResponse;
/**
 * 消息接受处理类
 */
public class HiHandler extends SimpleChannelHandler {

    /**
     * 接收消息
     */
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
            Response message = (Response)e.getMessage();//解码出来的之后是Response对象,然后进行业务处理

            if(message.getModule() == 1){
                
                if(message.getCmd() == 1){
                    FightResponse fightResponse = new FightResponse();
                    fightResponse.readFromBytes(message.getData());
                    
                    System.out.println("gold:" + fightResponse.getGold());
                    
                }else if(message.getCmd() == 2){
                    
                }
                
            }else if (message.getModule() == 1){
                
                
            }
    }

    /**
     * 捕获异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("exceptionCaught");
        super.exceptionCaught(ctx, e);
    }

    /**
     * 新连接
     */
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("channelConnected");
        super.channelConnected(ctx, e);
    }

    /**
     * 必须是链接已经建立,关闭通道的时候才会触发
     */
    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("channelDisconnected");
        super.channelDisconnected(ctx, e);
    }

    /**
     * channel关闭的时候触发
     */
    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("channelClosed");
        super.channelClosed(ctx, e);
    }
}

服务端:

package com.server;

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

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 org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

import com.cn.codc.RequestDecoder;
import com.cn.codc.ResponseEncoder;
/**
 * netty服务端入门
 */
public class Server {

    public static void main(String[] args) {

        //服务类
        ServerBootstrap bootstrap = new ServerBootstrap();
        
        //boss线程监听端口,worker线程负责数据读写
        ExecutorService boss = Executors.newCachedThreadPool();
        ExecutorService worker = Executors.newCachedThreadPool();
        
        //设置niosocket工厂
        bootstrap.setFactory(new NioServerSocketChannelFactory(boss, worker));
        
        //设置管道的工厂
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            
            @Override
            public ChannelPipeline getPipeline() throws Exception {

                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("decoder", new RequestDecoder());//Request的解码器
                pipeline.addLast("encoder", new ResponseEncoder());//Response的编码器
                pipeline.addLast("helloHandler", new HelloHandler());
                return pipeline;
            }
        });
        bootstrap.bind(new InetSocketAddress(10101));
        System.out.println("start!!!");
    }
}
package com.server;

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

import com.cn.model.Request;
import com.cn.model.Response;
import com.cn.model.StateCode;
import com.cn.module.fuben.request.FightRequest;
import com.cn.module.fuben.response.FightResponse;
/**
 * 消息接受处理类
 */
public class HelloHandler extends SimpleChannelHandler {

    /**
     * 接收消息
     */
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {

        Request message = (Request)e.getMessage();
        
        if(message.getModule() == 1){
            
            if(message.getCmd() == 1){
                
                FightRequest fightRequest = new FightRequest();
                fightRequest.readFromBytes(message.getData());
                
                System.out.println("fubenId:" +fightRequest.getFubenId() + "   " + "count:" + fightRequest.getCount());
                
                //回写数据
                FightResponse fightResponse = new FightResponse();
                fightResponse.setGold(9999);
                
                Response response = new Response();
                response.setModule((short) 1);
                response.setCmd((short) 1);
                response.setStateCode(StateCode.SUCCESS);
                response.setData(fightResponse.getBytes());
                ctx.getChannel().write(response);
            }else if(message.getCmd() == 2){
            }
        }else if (message.getModule() == 1){
        }
    }

    /**
     * 捕获异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("exceptionCaught");
        super.exceptionCaught(ctx, e);
    }

    /**
     * 新连接
     */
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("channelConnected");
        super.channelConnected(ctx, e);
    }

    /**
     * 必须是链接已经建立,关闭通道的时候才会触发
     */
    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("channelDisconnected");
        super.channelDisconnected(ctx, e);
    }

    /**
     * channel关闭的时候触发
     */
    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("channelClosed");
        super.channelClosed(ctx, e);
    }
}

网络传的是字节数据不是字符。

Netty之自定义数据包协议:
give me a coffee give me a tea (2条信息)

give me a coffeegive me a tea 粘包现象(2条信息粘在一起)

give me
a coffeegive me a tea 分包现象(第一条消息分开了,第一条后部分又粘到了第二条消息)

粘包和分包出现的原因是:没有一个稳定数据结构(没有确定一个请求传递哪些数据)

分割符:
give me a coffee|give me a tea|
give me a coffee|
give me a tea|

长度 + 数据:
16give me a coffee13give me a tea(读取16个就封装成一个请求,投递到业务层去)
16give me a coffee
13give me a tea

原文地址:https://www.cnblogs.com/yaowen/p/9063061.html