现在的位置: 首页 > 综合 > 正文

Netty学习

2014年06月15日 ⁄ 综合 ⁄ 共 2786字 ⁄ 字号 评论关闭

使用netty实现一个tcp的echo服务器。

(1)导入netty 的jar

(2)在主文件中搭建框架

package com.xing.echoserver;

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

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
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;

public class DiscardServer {

    public static void main(String[] args) throws Exception {
        ChannelFactory factory =
            new NioServerSocketChannelFactory(
                    Executors.newCachedThreadPool(),
                    Executors.newCachedThreadPool());

        ServerBootstrap bootstrap = new ServerBootstrap(factory);

        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                return Channels.pipeline(new DiscardServerHandler());//这里的DiscardServerHandler实现我们的逻辑,需要
            }
        });

        bootstrap.setOption("child.tcpNoDelay", true);//设置连接的一些属性
        bootstrap.setOption("child.keepAlive", true);

        bootstrap.bind(new InetSocketAddress(1872));//设置本地端口
    }
}

对于上面的代码大部分是框架性质的我们先不去深究,把有注释的几个地方搞清楚就够。

(3)在类中实现我们的业务逻辑。

package com.xing.echoserver;

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

public class DiscardServerHandler extends SimpleChannelHandler {

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {//收到消息是怎么办
    	Channel ch = e.getChannel();//拿到连接
        ch.write(e.getMessage());//将收到的消息写回连接
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        e.getCause().printStackTrace();
        
        Channel ch = e.getChannel();
        ch.close();
    }
}

(4)下面我们实现另外一个服务器-Time服务端程序,他的功能要求在客户端连接过来后,server马上发送一个当前的时间值(int类型的数据),而且发送成功之后马上关闭连接。

这里我们要重写的方法就不是messageReceived了,而是chennelConnected.

package org.jboss.netty.example.time;

public class TimeServerHandler extends SimpleChannelHandler {

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
        Channel ch = e.getChannel();//注意这里的Channel我们要引用netty包下面的Channel,而不是NIO包里面的Channel,因为netty对NIO的实现进行了增强。
        
        ChannelBuffer time = ChannelBuffers.buffer(4);//ChannelBuffers是一个帮助类,为我们实现分配buffer的功能,我们要发送一个int所以申请buffer 的长度是4
        time.writeInt((int) (System.currentTimeMillis() / 1000));
        
        ChannelFuture f = ch.write(time);//这里我们不需要flip,因为这里是netty的世界,不是NIO的世界,在这里ChannelBuffer有read、write两个指针分别用于读、写,方便多了。而且这里我们返回一个ChannelFuture,我们这么做是为了实现异步调用。我们不能马上调用ch.close
        
        f.addListener(new ChannelFutureListener() {//这里是一个匿名内部类,在完成write操作之后,Netty框架会执行operationComplete方法里面的代码
            public void operationComplete(ChannelFuture future) {
                Channel ch = future.getChannel();
                ch.close();
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        e.getCause().printStackTrace();
        e.getChannel().close();
    }
}

(5)Netty实现time 协议的客户端

抱歉!评论已关闭.