從入門到超神進(jìn)階的Netty群聊系統(tǒng)
服務(wù)端
服務(wù)端一樣的需要創(chuàng)建BossGroup 和 WorkGroup , 然后使用ServerBootStrap 來配置Netty和啟動Netty。
public class NettyGroupChatServer { public static void main(String[] args) { new NettyGroupChatServer().start(); } //監(jiān)聽 public void start(){ //循環(huán)組 NioEventLoopGroup bossGroup = new NioEventLoopGroup(); NioEventLoopGroup workGroup = new NioEventLoopGroup(); //啟動引導(dǎo) ServerBootstrap bootstrap = new ServerBootstrap(); //Netty配置 bootstrap.group(bossGroup,workGroup) .option(ChannelOption.SO_BACKLOG,32) .childOption(ChannelOption.SO_KEEPALIVE,true) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel channel) throws Exception { //解碼器 channel.pipeline().addLast("decoder", new StringDecoder()); //編碼器 channel.pipeline().addLast("encoder",new StringEncoder()); //處理器 channel.pipeline().addLast("nettyGroupChatHandler",new NettyGroupChatServerHandler()); } }); try { //啟動服務(wù) ChannelFuture future = bootstrap.bind(new InetSocketAddress("127.0.0.1", 8888)).sync(); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { //關(guān)閉資源 bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } }
服務(wù)端處理器我們通過繼承 SimpleChannelInboundHandler 入站Handler來處理消息。
其中提供了幾個方法
- channelRead0 ():讀取消息
- handlerRemoved ():客戶端斷開
- handlerAdded ():客戶端建立連接
- exceptionCaught ():出現(xiàn)異常
具體代碼如下
public class NettyGroupChatServerHandler extends SimpleChannelInboundHandler<String> { //把所有客戶端的channel保存起來 private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { String message = dateFormat.format(new Date())+":%s:"+msg; //消息轉(zhuǎn)發(fā)給所有的客戶端 channels.forEach(channel -> { if(channel == ctx.channel()){ String sendMsg = String.format(message, "我"); channel.writeAndFlush(sendMsg); System.out.println(sendMsg); }else{ String sendMsg = String.format(message, ctx.channel().remoteAddress()); channel.writeAndFlush(sendMsg); System.out.println(sendMsg); } }); } //斷開連接 , 把消息廣播給其他客戶端 @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":斷開連接"; channels.writeAndFlush(message); System.out.println(message); } //建立連接 @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":加入聊天室"; //自動把消息廣播給其客戶端 channels.writeAndFlush(message); //客戶端加入組 channels.add(ctx.channel()); System.out.println(message); } //出現(xiàn)異常 @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().close(); } //客戶端退出 @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":退出聊天室"; System.out.println(message); } //客戶端出于活動 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":上線啦"; System.out.println(message); } }
客戶端
客戶端需要創(chuàng)建一個循環(huán)事件組,然后通過BootStrap去啟動,然后掃描鍵盤輸入作為數(shù)據(jù)源來把信息發(fā)送給服務(wù)端
public class NettyGroupChatClient { public static void main(String[] args) { new NettyGroupChatClient().start(); } public void start(){ NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(eventLoopGroup) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel channel) throws Exception { //解碼器 channel.pipeline().addLast("decoder", new StringDecoder()); //編碼器 channel.pipeline().addLast("encoder",new StringEncoder()); //處理器 channel.pipeline().addLast("nettyGroupChatClientHandler",new NettyGroupChatClientHandler()); } }); try { ChannelFuture future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 8888)).sync(); //通道 Channel channel = future.channel(); //掃描鍵盤輸入 Scanner scanner = new Scanner(System.in); while(scanner.hasNextLine()){ String message = scanner.nextLine(); //發(fā)送數(shù)據(jù) channel.writeAndFlush(message); } } catch (InterruptedException e) { }finally { eventLoopGroup.shutdownGracefully(); } } }
對于處理器只需要接收服務(wù)端轉(zhuǎn)發(fā)過來的消息即可
public class NettyGroupChatClientHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println(msg); } }
啟動服務(wù)端和多個客戶端,效果如下
到此這篇關(guān)于從入門到超神系列的Netty群聊系統(tǒng)的文章就介紹到這了,更多相關(guān)Netty群聊系統(tǒng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法
本篇文章主要介紹了詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03使用SSM+Layui+Bootstrap實現(xiàn)汽車維保系統(tǒng)的示例代碼
本文主要實現(xiàn)對汽車維修廠的信息化管理功能,。實現(xiàn)的主要功能包含用戶管理、配置管理、汽車管理、故障管理、供應(yīng)商管理、配件管理、維修訂單管理、統(tǒng)計信息、公告管理、個人信息管理,感興趣的可以了解一下2021-12-12SpringBoot手動開啟事務(wù):DataSourceTransactionManager問題
這篇文章主要介紹了SpringBoot手動開啟事務(wù):DataSourceTransactionManager問題,具有很好的價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07springboot 使用Spring Boot Actuator監(jiān)控應(yīng)用小結(jié)
本篇文章主要介紹了springboot 使用Spring Boot Actuator監(jiān)控應(yīng)用小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02