netty学习三:基于socket的聊天小demo

来源:互联网 发布:抚顺市政府采购网域名 编辑:程序博客网 时间:2024/05/25 21:37

服务端代码


package chat.server;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;public class ChatServer {    public static void main(String[] args) throws InterruptedException {        // 接收连接,但是不处理        EventLoopGroup parentGroup = new NioEventLoopGroup();        // 真正处理连接的group        EventLoopGroup childGroup = new NioEventLoopGroup();        try {            //加载Initializer            ServerBootstrap serverBootstrap = new ServerBootstrap();            serverBootstrap.group(parentGroup, childGroup)                           .channel(NioServerSocketChannel.class)                           //这里的childHandler是服务于childGroup的,如果直接使用                           //handler方法添加处理器,则是服务于parentGroup的                           .childHandler(new ChatServerInitializer());            //绑定监听端口            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();            channelFuture.channel().closeFuture().sync();        }        finally {            parentGroup.shutdownGracefully();            childGroup.shutdownGracefully();        }    }}package chat.server;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.Delimiters;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import io.netty.util.CharsetUtil;public class ChatServerInitializer extends ChannelInitializer<SocketChannel>{    @Override    protected void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline = ch.pipeline();        //1、按照分隔符切割消息        pipeline.addLast(new DelimiterBasedFrameDecoder(4096,Delimiters.lineDelimiter()));        //2、socket编程中需要对字符串进行编码解码        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));        pipeline.addLast(new ChatServerHandler());    }}package chat.server;import io.netty.channel.Channel;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.channel.group.ChannelGroup;import io.netty.channel.group.DefaultChannelGroup;import io.netty.util.concurrent.GlobalEventExecutor;public class ChatServerHandler extends SimpleChannelInboundHandler<String>{    //存放所有channel对象    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);     @Override    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {        Channel channel = ctx.channel();        channelGroup.forEach(ch -> {            if (channel != ch) {                ch.writeAndFlush(channel.remoteAddress()+" 发送的:"+msg+"\n");            }            else {                ch.writeAndFlush("本人发的消息:"+msg + "\n");            }        });    }    @Override    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {        Channel channel = ctx.channel();        channelGroup.writeAndFlush("有人:"+channel.remoteAddress()+"加入\n");        channelGroup.add(channel);    }    @Override    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {        Channel channel = ctx.channel();        channelGroup.writeAndFlush("有人:"+channel.remoteAddress()+"离开\n");           }    @Override    public void channelActive(ChannelHandlerContext ctx) throws Exception {        Channel channel = ctx.channel();        System.out.println(channel.remoteAddress() + "上线");    }    @Override    public void channelInactive(ChannelHandlerContext ctx) throws Exception {        Channel channel = ctx.channel();        System.out.println(channel.remoteAddress() + "上线");    }}

客户端代码


package chat.client;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import io.netty.bootstrap.Bootstrap;import io.netty.channel.Channel;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioSocketChannel;public class ChatClient {    public static void main(String[] args) throws InterruptedException, IOException {        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();        try {            //加载Initializer            Bootstrap bootstrap = new Bootstrap();            bootstrap.group(eventLoopGroup)                           .channel(NioSocketChannel.class)                           .handler(new ChatClientInitializer());            //连接服务端            Channel channel = bootstrap.connect("localhost", 8899).sync().channel();            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));            for(;;) {                channel.writeAndFlush(br.readLine() + "\r\n");            }        }        finally {            eventLoopGroup.shutdownGracefully();        }    }}package chat.client;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.Delimiters;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import io.netty.util.CharsetUtil;public class ChatClientInitializer extends ChannelInitializer<SocketChannel>{    @Override    protected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();        //1、按照分隔符切割消息        pipeline.addLast(new DelimiterBasedFrameDecoder(4096,Delimiters.lineDelimiter()));        //2、socket编程中需要对字符串进行编码解码        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));        //3、添加自定义处理器        pipeline.addLast(new ChatClientHandler());    }}package chat.client;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;public class ChatClientHandler extends SimpleChannelInboundHandler<String>{    @Override    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {        System.out.println(msg);    }}

当有新的客户端连接到服务器的时候,ChatServerHandler的channelRead0方法会给所有上线的客户端发送消息。

ChatClient的main方法中,会从System.in中获取用户的输入,并写到服务端。


csdn code 路径


这个项目的源代码放置在csdn code上,欢迎访问。

netty_study