netty的简单实现

来源:互联网 发布:加入网络作协要求 编辑:程序博客网 时间:2024/05/20 14:16

概述

       本篇博客通过简单的demo实现netty的使用

netty3

       1、添加netty3的maven依赖

       <dependency>            <groupId>org.jboss.netty</groupId>            <artifactId>netty</artifactId>            <version>3.2.10.Final</version>        </dependency>

       2、服务端的demo

package five.heart3;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 org.jboss.netty.handler.timeout.IdleStateHandler;import org.jboss.netty.util.HashedWheelTimer;import java.net.InetSocketAddress;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午5:56 * netty服务端 */public class Server {    public static void main(String[] args){        //服务类        ServerBootstrap serverBootstrap = new ServerBootstrap();        //boss线程监听端口,worker线程负责数据读写        ExecutorService boss = Executors.newCachedThreadPool();        ExecutorService worker = Executors.newCachedThreadPool();        //设置NioSocket工厂        serverBootstrap.setFactory(new NioServerSocketChannelFactory(boss,worker));        final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(); //定时器        //设置管道的工厂        serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {            @Override            public ChannelPipeline getPipeline() throws Exception {                 ChannelPipeline channelPipeline = Channels.pipeline();                //定时器,读超时,写超时,读写超时                channelPipeline.addLast("idle",new IdleStateHandler(hashedWheelTimer,5,5,10));                channelPipeline.addLast("decoder",new StringDecoder());                channelPipeline.addLast("encoder",new StringEncoder());                channelPipeline.addLast("helloHandler",new HelloHandler());                return channelPipeline;            }        });        //netty3中对应设置如下        serverBootstrap.setOption("backlog",1024); //ServerSocketChannel的设置,链接缓冲池的大小        serverBootstrap.setOption("keepAlive",true);//socketChannel的设置,维持链接的活跃,清楚死链接        serverBootstrap.setOption("tcpNoDelay",true); //socketChannel的设置,关闭延迟发送        serverBootstrap.bind(new InetSocketAddress(10101));        System.out.println("start!!!");    }}

package five.heart3;import org.jboss.netty.channel.*;import org.jboss.netty.handler.timeout.IdleState;import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;import org.jboss.netty.handler.timeout.IdleStateEvent;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午6:17 * To change this template use File | Settings | File Templates. *///public class HelloHandler extends SimpleChannelHandler {public class HelloHandler extends IdleStateAwareChannelHandler implements  ChannelHandler {    @Override    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {        System.out.println(e.getMessage());    }    @Override    public void handleUpstream(final ChannelHandlerContext ctx, ChannelEvent e) throws Exception {        if(e instanceof IdleStateEvent){            if(((IdleStateEvent)e).getState() == IdleState.ALL_IDLE){                System.out.println("提玩家下线");                ChannelFuture channelFuture = ctx.getChannel().write("time out,you will close");                channelFuture.addListener(new ChannelFutureListener() {                    @Override                    public void operationComplete(ChannelFuture future) throws Exception {                        ctx.getChannel().close();                    }                });            }        }else{            super.handleUpstream(ctx,e);        }    }} 

netty5

       1、添加netty5的maven依赖

        <dependency>            <groupId>io.netty</groupId>            <artifactId>netty-all</artifactId>            <version>5.0.0.Alpha2</version>        </dependency>

       2、服务端的demo

package five.heart5;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.*;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import io.netty.handler.timeout.IdleStateHandler;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午7:18 * To change this template use File | Settings | File Templates. */public class Server {    public static void main(String[] args){        //服务类        ServerBootstrap serverBootstrap = new ServerBootstrap();        //boss和worker        EventLoopGroup boss = new NioEventLoopGroup();        EventLoopGroup worker = new NioEventLoopGroup();        try{            //设置线程池            serverBootstrap.group(boss,worker);            //设置NioSocket工厂            serverBootstrap.channel(NioServerSocketChannel.class);            //设置管道工厂            serverBootstrap.childHandler(new ChannelInitializer<Channel>() {                @Override                protected void initChannel(Channel channel) throws Exception {                    channel.pipeline().addLast(new IdleStateHandler(5,5,10));                    channel.pipeline().addLast(new StringDecoder());                    channel.pipeline().addLast(new StringEncoder());                    channel.pipeline().addLast(null);                }            });            //设置参数,TCP参数            serverBootstrap.option(ChannelOption.SO_BACKLOG,2048);//ServerSocketChannel的设置,链接缓冲池的大小            serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE,true);//socketChannel的设置,维持链接的活跃,清楚死链接            serverBootstrap.childOption(ChannelOption.TCP_NODELAY,true);//socketChannel的设置,关闭延迟发送            //绑定端口            ChannelFuture channelFuture = serverBootstrap.bind(10101);            System.out.println("start");            //等待服务端关闭            channelFuture.channel().closeFuture().sync();        }catch (Exception ex){            ex.printStackTrace();        }finally {            //释放资源            boss.shutdownGracefully();            worker.shutdownGracefully();        }    }}

package five.heart5;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.timeout.IdleStateEvent;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午7:29 * To change this template use File | Settings | File Templates. */public class ServerHandler extends SimpleChannelInboundHandler<String> {    @Override    protected void messageReceived(ChannelHandlerContext channelHandlerContext, String msg) throws Exception {        System.out.println(msg);        channelHandlerContext.channel().writeAndFlush("hi");        channelHandlerContext.writeAndFlush("hi");    }    @Override    public void userEventTriggered(final ChannelHandlerContext channelHandlerContext,Object evt) throws Exception{        if(evt instanceof IdleStateEvent){        }    }}

客户端

       1、可以使用telnet进行测试上面的服务器端

       2、可以编程netty的单client端

package four.client;import io.netty.bootstrap.Bootstrap;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.NioSocketChannel;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import java.io.BufferedReader;import java.io.InputStreamReader;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午4:01 * To change this template use File | Settings | File Templates. */public class Client {    public static void main(String[] args){        //服务类        Bootstrap bootstrap = new Bootstrap();        //worker        EventLoopGroup worker = new NioEventLoopGroup();        try{            //设置线程池            bootstrap.group(worker);            //设置socket工厂            bootstrap.channel(NioSocketChannel.class);            //设置管道            bootstrap.handler(new ChannelInitializer<Channel>() {                @Override                protected void initChannel(Channel channel) throws Exception {                    channel.pipeline().addLast(new StringDecoder());                    channel.pipeline().addLast(new StringEncoder());                    channel.pipeline().addLast(new ClientHandler());                }            });            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 10101);            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));            while (true){                System.out.println("请输入:");                String msg = bufferedReader.readLine();                channelFuture.channel().writeAndFlush(msg);            }        }catch (Exception ex){            ex.printStackTrace();        }finally {            worker.shutdownGracefully();        }    }}

package four.client;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午4:08 * To change this template use File | Settings | File Templates. */public class ClientHandler extends SimpleChannelInboundHandler<String> {    @Override    protected void messageReceived(ChannelHandlerContext channelHandlerContext, String msg) throws Exception {        System.out.println("客户端收到消息:"+msg);    }}

       3、可以编程netty的多client端

package four.client;import io.netty.bootstrap.Bootstrap;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.NioSocketChannel;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import java.util.ArrayList;import java.util.List;import java.util.concurrent.atomic.AtomicInteger;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午4:18 * 多连接客户端 */public class MultClient {    //服务类    private Bootstrap bootstrap = new Bootstrap();    //会话:Channel对象是线程安全的对象    private List<Channel> channels = new ArrayList<>();    //引用计数    private final AtomicInteger atomicInteger = new AtomicInteger();    //引用计数    public void init(int count){        //worker        EventLoopGroup worker = new NioEventLoopGroup();        //设置线程池        bootstrap.group(worker);        //设置socket工厂        bootstrap.channel(NioSocketChannel.class);        //设置管道        bootstrap.handler(new ChannelInitializer<Channel>() {            @Override            protected void initChannel(Channel channel) throws Exception {                channel.pipeline().addLast(new StringDecoder());                channel.pipeline().addLast(new StringEncoder());                channel.pipeline().addLast(new ClientHandler());            }        });        for(int i=1;i<=count;i++){            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",10101);            channels.add(channelFuture.channel());        }    }    //获取会话    public Channel nextChannel(){        return getFirstActiveChannel(0);    }    private Channel getFirstActiveChannel(int count){        Channel channel = channels.get(Math.abs(atomicInteger.getAndIncrement() % channels.size()));        if(!channel.isActive()){            //重连            reconnect(channel);            if(count>=channels.size()){                throw new RuntimeException("no can use channel");            }            return getFirstActiveChannel(count + 1);        }        return channel;    }    //重连    private void reconnect(Channel channel){        synchronized (channel){            if(channels.indexOf(channel) == -1){                return;            }            Channel newChannel = bootstrap.connect("127.0.0.1",10101).channel();            channels.set(channels.indexOf(channel),newChannel);        }    }}

package four.client;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;/** * Created with IntelliJ IDEA. * User: ipaynow * Date: 17-6-24 * Time: 下午4:56 * To change this template use File | Settings | File Templates. */public class Start {    public static void main(String[] args) {        MultClient client = new MultClient();        client.init(5);        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));        while (true){            try {                System.out.println("请输入:");                String msg = bufferedReader.readLine();                client.nextChannel().writeAndFlush(msg);            } catch (IOException e) {                e.printStackTrace();            }        }    }}

总结

       关于netty的使用基本上就是上面的内容,在netty的多链接客户端中Channel是线程安全的(新线程时,会写时会将该内容分装成一个任务,给一个单线程池),所以我们当我们多个线程操作同一个Channel对象的时候,是不会出现线程安全的问题,所以,在netty的多链接客户端中采用的是对象组而不是对象池。



原创粉丝点击