Netty 实例

网上的netty资料很少,感觉很少有人分享这方面的东西,最近捣鼓了下netty,一哥们说还不错,做底层通信,呵呵 ,测试结果 还不错 ,目前打算作为项目的备用底层通信方案 不说其他的 直接上代码,分享下 。有什么疑问直接留言。


package com.commons.nettyCore;

import com.commons.logger.NioSocket_log;
import com.commons.nettyCore.MServerconfig.MServerConfig;
import org.jboss.netty.channel.*;
import org.jboss.netty.handler.timeout.IdleState;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelUpstreamHandler;
import org.jboss.netty.handler.timeout.IdleStateEvent;
import org.jboss.netty.util.Timer;

/**
 * Created with IntelliJ IDEA.
 * User: CHENLEI
 * Date: 12-10-28
 * Time: 下午7:45
 * To change this template use File | Settings | File Templates.
 * channelPipeFactory &Timer
 */
public class MServerChannelPipelineFactory extends IdleStateAwareChannelUpstreamHandler implements ChannelPipelineFactory {

    private Timer timer=null;
    private ChannelHandler idleStateHandler=null;

    /**
     *
     * @param timer 定时器
     * @param idleStateHandler
     */
    public MServerChannelPipelineFactory(Timer timer, ChannelHandler idleStateHandler){
           this.timer=timer;
           this.idleStateHandler=idleStateHandler;
    }

    private MServerChannelPipelineFactory(){}

    /**
     * Returns a newly created {@link org.jboss.netty.channel.ChannelPipeline}.
     */
    @Override
    public ChannelPipeline getPipeline() throws Exception {
        ChannelPipeline pipeline= Channels.pipeline(this.idleStateHandler, new MServerChannelPipelineFactory());
        pipeline.addLast("decoder", MServerDecoder.getDecoder());
        pipeline.addLast("handler", MServerHandler.getMServerHandler());
        pipeline.addLast("encoder", MServerEncoder.getEncoder());
        return pipeline;  //To change body of implemented methods use File | Settings | File Templates.
    }

    /**
     * 超时处理  。。。。
     * @param ctx
     * @param e
     */
    @Override
    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) {
        Channel c=e.getChannel();
        if (e.getState() == IdleState.READER_IDLE) {
            if(MServerConfig.debug) NioSocket_log.log.info(c.getRemoteAddress()+"--connect timeout");
            c.close();
            /**
             * 回写玩家数据
             */
        }
    }

}
package com.commons.nettyCore;




import com.commons.logger.NioSocket_log;
import com.commons.nettyCore.MServerconfig.MServerConfig;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

/**
 *   数据解析类
 *   获取的数据存放在字节队列中
 */
public class MServerDecoder extends FrameDecoder {

    private MServerDecoder(){}

    public static MServerDecoder getDecoder(){
        return singlton.mserverDecoder;
    }

    /**
     *
     * @param ctx
     * @param channel
     * @param buffer  非共享 “one” --当接收完毕一个消息后 丢弃
     * @return
     * @throws Exception
     */
    @Override
    protected Object decode(
            ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
//        NioSocket_log.log.info(channel.getRemoteAddress() + "connection server.");
        if (buffer.readableBytes() < MServerConfig.packlen) {//可读字节小包长2,等待下一次读事件
            return null;
        }
        //pack_length
        int dataLength =  buffer.getShort(buffer.readerIndex());

        if (buffer.readableBytes() < dataLength + MServerConfig.packlen) { //可读字节数小于一个完整的包,等待下一次读事件

            return null;
        }
        buffer.skipBytes(MServerConfig.packlen);  //skip pack_length bytes  2

        byte[] pack = new byte[dataLength];
        buffer.readBytes(pack);

        if(MServerConfig.debug) NioSocket_log.log.info("reciveMessage:"+ new String(pack).trim());
        return pack;  //FrameDecoder将继续调用 decode()
    }

    private static final class singlton{
        private static final MServerDecoder mserverDecoder=new MServerDecoder();
    }
}
package com.commons.nettyCore;


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


/**
 * MServerEncoder
 */
@Sharable
public class MServerEncoder extends OneToOneEncoder {
//     private MSession mSession;

     private MServerEncoder(){}


    public static MServerEncoder getEncoder(){
        return Singleton.mencoder;
    }

    // OneToOneEncoder调用Channels.write(),将数据推送回client
    @Override
    protected Object encode(
            ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
        if (!(msg instanceof ChannelBuffer)){
            return null;
        }
        return msg;
    }

    private static final  class Singleton{
        private static final  MServerEncoder mencoder=new MServerEncoder();
    }

}
package com.commons.nettyCore;


import com.commons.define.BaseDefinition;
import com.commons.logger.NioSocket_log;
import com.commons.logic.DataProcess;
import com.commons.nettyCore.MServerconfig.MServerConfig;
import game.user.User;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;

/**
* SimpleChannelUpstreamHandler提供多种事件重写的方法</br>
* 服务端业务处理handler</br>
*/
@ChannelPipelineCoverage("all")    //一个处理器是否可以被多个channel共享
public class MServerHandler extends SimpleChannelHandler {

     private MSocket mSession=null;
     private MServerHandler(){}


    /**
     * 获取messageServerHandler
     * @return
     */
    public static MServerHandler getMServerHandler(){
        return siglton.mServerHandler;
    }

    /**
     * 获取ChannelGroup--管理channel集合
     * @return
     */
     public static ChannelGroup getChannelGrop(){
         return siglton.chanelGrop;
     }

    /**
     * Invoked when a message object (e.g: {@link org.jboss.netty.buffer.ChannelBuffer}) was received
     * from a remote peer.
     */
    @Override
    public void messageReceived(
            ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException {
        byte []pack= (byte[]) e.getMessage();
        if (pack!=null)this.mSession.getHandBuffers().add((byte[]) e.getMessage());
        if(this.mSession.getHandBuffers().size()>0) DataProcess.getDataProcess().onData(this.mSession);

    }

    /**
     * 异常处理
     * @param ctx
     * @param e
     */
    @Override
    public void exceptionCaught(
            ChannelHandlerContext ctx, ExceptionEvent e) {
        NioSocket_log.log.warn("Unexpected exception from downstream.", e.getCause());
        e.getChannel().close();
    }


    /**
     * 当建立一个连接时候触发
     * @param ctx
     * @param e
     * @throws Exception
     */
    @Override
    public void channelConnected(
            ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        Channel channel=e.getChannel();
        if (MServerConfig.debug) NioSocket_log.log.info(channel.getRemoteAddress()+"--connected server"+channel.getId());
        this.mSession=new MSocket(channel,ctx);//创建一个MSession
        ctx.setAttachment(this.mSession);


        User user = new User();
        user.setmSocket(mSession);
        BaseDefinition.SocketUserMaps.put(mSession, user);


    }


    /**
     * channel关闭触发事件
     * @param ctx
     * @param e
     * @throws Exception
     */
    @Override
    public void channelClosed(
            ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        Channel channel=e.getChannel();
        if (MServerConfig.debug)NioSocket_log.log.info(channel.getRemoteAddress()+"--disconnected server"+channel.getId());
        siglton.chanelGrop.remove(channel);
        /**
         * 持久化数据
         */
        ctx.sendUpstream(e);
    }

    /**
     * Invoked when a {@link org.jboss.netty.channel.Channel} is open, but not bound nor connected.
     * <br/>
     *
     * <strong>Be aware that this event is fired from within the Boss-Thread so you should not
     * execute any heavy operation in there as it will block the dispatching to other workers!</strong>
     */
    @Override
    public void channelOpen(
            ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
            siglton.chanelGrop.add(e.getChannel());
//        siglton.chanelGrop.size();
        ctx.sendUpstream(e);
    }


    private static final class siglton{
        private static final ChannelGroup chanelGrop=new DefaultChannelGroup();
        private static final MServerHandler mServerHandler=new MServerHandler();
    }
}
package com.commons.nettyCore;



import com.commons.logger.NioSocket_log;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;

import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Created with IntelliJ IDEA.
 * User: CHENLEI
 * Date: 12-10-28
 * Time: 下午11:06
 * To change this template use File | Settings | File Templates.
 * 会话,代表一个建立连接的客户端
 */
public  class MSocket{

    private Channel channel;
    private ChannelHandlerContext ctx;
    private final ConcurrentLinkedQueue<byte[]> HandBuffers = new ConcurrentLinkedQueue<byte[]>();
    private final ConcurrentLinkedQueue<ChannelBuffer> writeBuffers = new ConcurrentLinkedQueue<ChannelBuffer>();


    MSocket(Channel channel,ChannelHandlerContext ctx){
       this.channel=channel;
        this.ctx=ctx;
    }
    public Channel getChannel() {
        return channel;
    }

    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    /**
     * 添加channelbuffer在待发送的队列
     * @param buffer       ChannelBuffer
     */
    public  void addQueue(ChannelBuffer buffer) {
        if(buffer!=null){
         this.getWriteBuffers().add(buffer);
          NioSocket_log.log.info("添加数据buffer:"+ buffer);
           if (this.getWriteBuffers().size()>0){
               ChannelBuffer msg=this.getWriteBuffers().poll();
               channel.write(msg,channel.getRemoteAddress());
           }
        }else {
            NioSocket_log.log.error("buffer is nullException,please checked it");
        }
    }


    /**
     * 获取处理的缓存对列
     * @return
     */
    public ConcurrentLinkedQueue<byte[]> getHandBuffers() {
        return HandBuffers;
    }

    /**
     * 获取带发送的缓存队列
     * @return
     */
    public ConcurrentLinkedQueue<ChannelBuffer> getWriteBuffers() {
        return writeBuffers;
    }


}
package com.commons.nettyCore;



import com.commons.logger.NioSocket_log;
import com.commons.nettyCore.MServerconfig.MServerConfig;
import com.commons.nettyCore.SafeBox.SafeBox;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timer;

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

/**
 * Created with IntelliJ IDEA.
 * User: CHENLEI
 * Date: 12-10-30
 * Time: 上午11:03
 * To change this template use File | Settings | File Templates.
 * start netty
 */
public class nettyServer {

    private nettyServer(){}

    public static nettyServer getInstance(){
        return singelton.nettyserver;
    }

    public void startServer(){
        try{
            //初始化netty配置
            boolean status= MServerConfig.IntiServerConfig();
            if(!status)System.exit(0);

            /**
             * ChannelFactory创建和管理channel的以及相关资源的接口</br>
             * 处理相应的I/O请求,并产生相应的channelEvent</br>
             */
            ChannelFactory factory=new NioServerSocketChannelFactory( Executors.newCachedThreadPool(),
                    Executors.newCachedThreadPool(),MServerConfig.workerThread);

//            ChannelFactory factory=new NioServerSocketChannelFactory( Executors.newCachedThreadPool(),
//                    Executors.newCachedThreadPool(),MServerConfig.workerThread);
            // Configure the server.
            ServerBootstrap bootstrap = new ServerBootstrap(factory);
            /**
             *  当一个新的连接上来,创建新的ChannelPipeline对象
             *  所以添加的channelhandler对象将被添加在新创建的对象</br></>
             */

            Timer timer = new HashedWheelTimer();
            ChannelHandler idleStateHandler=new IdleStateHandler(timer, MServerConfig.readTimeOut,MServerConfig.writeTimeOut,0);
            bootstrap.setPipelineFactory(new MServerChannelPipelineFactory(timer,idleStateHandler));
//        bootstrap.releaseExternalResources();
            // Bind and start to accept incoming connections.
            bootstrap.setOption("tcpNoDelay", true);
            bootstrap.setOption("keepAlive", true);
            bootstrap.bind(new InetSocketAddress(MServerConfig.port));
            if(MServerConfig.debug) NioSocket_log.log.info("service is listen on port:"+MServerConfig.port);
            if(MServerConfig.isSafeopen)new SafeBox().startService();
        }catch (Exception e){
            NioSocket_log.log.error("netty start failed ",e);
        }

    }

    private static  final class singelton{
        private static final nettyServer nettyserver=new nettyServer();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <!--true:调试打印日志;false:运行打印日志-->
    <debug>true</debug>
    <!-- 服务端口 -->
    <port>8888</port>
    <!--netty worker线程数 -->
    <workerThread>3</workerThread>
    <!--read data time out   ..secs-->
    <readTimeOut>36000</readTimeOut>
    <!--write data time out   ..secs-->
    <writeTimeOut>0</writeTimeOut>
    <!--是否打开安全沙箱-->
    <isSafeopen>true</isSafeopen>

    <!--包长-->
    <packlen>2</packlen>
</root>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值