4、netty第三个例子,建立一个tcp的聊天的程序

代码基于第二个例子,支持多客户端的连接,在线聊天。

主要思路:

  连接建立时,在服务器端,保存channel 对象,当有新的客户端加入时,遍历保存的channel集合,向其他客户端发送加入消息。

  当一个客户端发送消息时,在服务器端,遍历channel集合,判断是否为发送者,来修改发送内容,如:    XX说:  我说:

同样的:

server中的主程序和第二个例子类似

server中的initializer

 1 import io.netty.channel.ChannelInitializer;
 2 import io.netty.channel.ChannelPipeline;
 3 import io.netty.channel.socket.SocketChannel;
 4 import io.netty.handler.codec.DelimiterBasedFrameDecoder;
 5 import io.netty.handler.codec.Delimiters;
 6 import io.netty.handler.codec.string.StringDecoder;
 7 import io.netty.handler.codec.string.StringEncoder;
 8 import io.netty.util.CharsetUtil;
 9 
10 public class MyChatServerInitlalizer extends ChannelInitializer<SocketChannel> {
11 
12     @Override
13     protected void initChannel(SocketChannel ch) throws Exception {
14         ChannelPipeline pipeline = ch.pipeline();
15         //解码器,根据分隔符来分割
16         pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));
17         pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));//编码
18         pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));//解码
19 
20         pipeline.addLast(new MyChatServerHandler());
21 
22     }
23 }

server中的handler

 1 import io.netty.channel.Channel;
 2 import io.netty.channel.ChannelHandlerContext;
 3 import io.netty.channel.SimpleChannelInboundHandler;
 4 import io.netty.channel.group.ChannelGroup;
 5 import io.netty.channel.group.DefaultChannelGroup;
 6 import io.netty.util.concurrent.GlobalEventExecutor;
 7 
 8 public class MyChatServerHandler extends SimpleChannelInboundHandler<String> {
 9 
10     //这个对象可以获取到所有的channel
11     private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
12 
13 
14     @Override
15     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
16         cause.printStackTrace();
17         ctx.close();
18     }
19 
20     @Override
21     protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
22         Channel channel = ctx.channel();
23 
24         channelGroup.forEach(ch -> {
25             System.out.println("ii");
26             if(ch != channel) {
27                 System.out.println("othor");
28                 ch.writeAndFlush(channel.remoteAddress() + "发送的消息:" + msg + "\n");//发送消息出去的时候,这个\n,一定不能丢,不然发不出去
29             } else {
30                 ch.writeAndFlush( "自己: " + msg + "\n");
31             }
32         });
33 
34         //服务器接收到消息,相所有客户端 发送 消息
35         System.out.println("接收到 " + channel.remoteAddress() +" 客户端的消息:" + msg);
36 //        //发送给其他客户端
37 //        ctx.writeAndFlush("msg");
38     }
39 
40     @Override
41     public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
42         Channel channel = ctx.channel();//获取到连接
43         //告诉已有的其他连接
44         channelGroup.writeAndFlush("[服务器] - " + channel.remoteAddress() + " - 加入\n");
45         //再加入
46         channelGroup.add(channel);//把channel加到channelGroup
47     }
48 
49     @Override
50     public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
51         Channel channel = ctx.channel();
52         channelGroup.writeAndFlush("[服务器] - " + channel.remoteAddress() + "已离开\n");
53 //        channelGroup.remove(channel);//netty会自动将已经失去连接的channel,从channelGroup 中移除
54     }
55 
56     @Override
57     public void channelActive(ChannelHandlerContext ctx) throws Exception {
58         Channel channel = ctx.channel();
59         System.out.println(channel.remoteAddress() + "上线了!");
60     }
61 
62     @Override
63     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
64         Channel channel = ctx.channel();
65         System.out.println(channel.remoteAddress() + "下线了!");
66     }
67 }

clien中的主程序

 1 import io.netty.bootstrap.Bootstrap;
 2 import io.netty.channel.Channel;
 3 import io.netty.channel.ChannelFuture;
 4 import io.netty.channel.EventLoopGroup;
 5 import io.netty.channel.nio.NioEventLoopGroup;
 6 import io.netty.channel.socket.nio.NioSocketChannel;
 7 
 8 import java.io.BufferedReader;
 9 import java.io.IOException;
10 import java.io.InputStreamReader;
11 
12 public class MyChatClient {
13     public static void main(String[] args) throws InterruptedException, IOException {
14         //客户端只需要一个
15         EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
16 
17         try{
18 
19             Bootstrap bootstrap = new Bootstrap();
20             bootstrap.group(eventLoopGroup)
21                     .channel(NioSocketChannel.class)
22                     .handler(new MyChatInitlaizer());
23             ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync();
24 
25             Channel channel = channelFuture.channel();
26 
27             //channelFuture.channel().writeAndFlush("first msg");//发送数据,其实应该写到handler的active方法中
28 
29             BufferedReader br = new BufferedReader(new InputStreamReader( System.in));
30             for (;;) {//死循环来接收客户端的输入
31                 channel.writeAndFlush(br.readLine() + "\r\n");
32             }
33 
34 //           channelFuture.channel().closeFuture().sync();
35         }finally {
36             eventLoopGroup.shutdownGracefully();
37         }
38 
39     }
40 }

client中的initializer和服务器端的类似

client中的handle,只要简单输出就行。

扫描二维码关注公众号,回复: 7148423 查看本文章

猜你喜欢

转载自www.cnblogs.com/amibandoufu/p/11442739.html
今日推荐