电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

JAVA Netty實現聊天室+私聊功能的示例代碼

瀏覽:5日期:2022-08-26 15:53:26

功能介紹

使用Netty框架實現聊天室功能,服務器可監控客戶端上下限狀態,消息轉發。同時實現了點對點私聊功能。技術點我都在代碼中做了備注,這里不再重復寫了。希望能給想學習netty的同學一點參考。

服務器代碼

服務器入口代碼

package nio.test.netty.groupChat;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.ChannelPipeline;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import io.netty.util.concurrent.Future;import io.netty.util.concurrent.GenericFutureListener;/** * netty群聊 服務器端 * @author zhang * */public class NettyChatServer {private int port;public NettyChatServer(int port){this.port = port;}//初始化 netty服務器private void init() throws Exception{EventLoopGroup boss = new NioEventLoopGroup(1);EventLoopGroup work = new NioEventLoopGroup(16);try {ServerBootstrap boot = new ServerBootstrap();boot.group(boss,work);boot.channel(NioServerSocketChannel.class);//設置boss selector建立channel使用的對象boot.option(ChannelOption.SO_BACKLOG, 128);//boss 等待連接的 隊列長度boot.childOption(ChannelOption.SO_KEEPALIVE, true); //讓客戶端保持長期活動狀態boot.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//從channel中獲取pipeline 并往里邊添加HandlerChannelPipeline pipeline = ch.pipeline();pipeline.addLast('encoder',new StringEncoder());pipeline.addLast('decoder',new StringDecoder());pipeline.addLast(new ServerMessageHandler());//自定義Handler來處理消息}});System.out.println('服務器開始啟動...');//綁定端口 ChannelFuture channelFuture = boot.bind(port).sync();channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {@Overridepublic void operationComplete(Future<? super Void> future)throws Exception {if(future.isSuccess()){System.out.println('服務器正在啟動...');}if(future.isDone()){System.out.println('服務器啟動成功...OK');}}});//監聽channel關閉channelFuture.channel().closeFuture().sync();channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {@Overridepublic void operationComplete(Future<? super Void> future)throws Exception {if(future.isCancelled()){System.out.println('服務器正在關閉..');}if(future.isCancellable()){System.out.println('服務器已經關閉..OK');}}});}finally{boss.shutdownGracefully();work.shutdownGracefully();}}/** * 啟動服務器 main 函數 * @param args * @throws Exception */public static void main(String[] args) throws Exception {new NettyChatServer(9090).init();}}

服務器端消息處理Handler

package nio.test.netty.groupChat;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;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * 自定義 服務器端消息處理Handler * @author zhang * */public class ServerMessageHandler extends SimpleChannelInboundHandler<String>{/** * 管理全局的channel * GlobalEventExecutor.INSTANCE 全局事件監聽器 * 一旦將channel 加入 ChannelGroup 就不要用手動去 * 管理channel的連接失效后移除操作,他會自己移除 */private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);/** * 為了實現私聊功能,這里key存儲用戶的唯一標識, * 我保存 客戶端的端口號 * 當然 這個集合也需要自己去維護 用戶的上下線 不能像 ChannelGroup那樣自己去維護 */private static Map<String,Channel> all = new HashMap<String,Channel>();private SimpleDateFormat sf = new SimpleDateFormat('yyyy-MM-dd HH:mm:ss');/** * 處理收到的消息 */@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg)throws Exception {Channel channel = ctx.channel();/** * 這里簡單判斷 如果內容里邊包含#那么就是私聊 */if(msg.contains('#')){String id = msg.split('#')[0];String body = msg.split('#')[1];Channel userChannel = all.get(id);String key = channel.remoteAddress().toString().split(':')[1];userChannel.writeAndFlush(sf.format(new Date())+'n 【用戶】 '+key+' 說 : '+body);return;}//判斷當前消息是不是自己發送的for(Channel c : channels){String addr = c.remoteAddress().toString();if(channel !=c){c.writeAndFlush(sf.format(new Date())+'n 【用戶】 '+addr+' 說 : '+msg);}else{c.writeAndFlush(sf.format(new Date())+'n 【自己】 '+addr+' 說 : '+msg);}}}/** * 建立連接以后第一個調用的方法 */@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();String addr = channel.remoteAddress().toString();/** * 這里 ChannelGroup 底層封裝會遍歷給所有的channel發送消息 * */channels.writeAndFlush(sf.format(new Date())+'n 【用戶】 '+addr+' 加入聊天室 ');channels.add(channel);String key = channel.remoteAddress().toString().split(':')[1];all.put(key, channel);}/** * channel連接狀態就緒以后調用 */@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {String addr = ctx.channel().remoteAddress().toString();System.out.println(sf.format(new Date())+' n【用戶】 '+addr+' 上線 ');}/** * channel連接狀態斷開后觸發 */@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {String addr = ctx.channel().remoteAddress().toString();System.out.println(sf.format(new Date())+' n【用戶】 '+addr+' 下線 ');//下線移除String key = ctx.channel().remoteAddress().toString().split(':')[1];all.remove(key);}/** * 連接發生異常時觸發 */@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {//System.out.println('連接發生異常!');ctx.close();}/** * 斷開連接會觸發該消息 * 同時當前channel 也會自動從ChannelGroup中被移除 */@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();String addr = channel.remoteAddress().toString();/** * 這里 ChannelGroup 底層封裝會遍歷給所有的channel發送消息 * */channels.writeAndFlush(sf.format(new Date())+'n 【用戶】 '+addr+' 離開了 ');//打印 ChannelGroup中的人數System.out.println('當前在線人數是:'+channels.size());System.out.println('all:'+all.size());}}

客戶端主方法代碼

package nio.test.netty.groupChat;import io.netty.bootstrap.Bootstrap;import io.netty.channel.Channel;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;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 io.netty.util.concurrent.Future;import io.netty.util.concurrent.GenericFutureListener;import java.util.Scanner;public class NettyChatClient {private String ip;private int port;public NettyChatClient(String ip,int port){this.ip = ip;this.port = port;}/** * 初始化客戶 */private void init() throws Exception{//創建監聽事件的監聽器EventLoopGroup work = new NioEventLoopGroup();try {Bootstrap boot = new Bootstrap();boot.group(work);boot.channel(NioSocketChannel.class);boot.handler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch)throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast('encoder',new StringEncoder());pipeline.addLast('decoder',new StringDecoder());pipeline.addLast(new ClientMessageHandler());}});ChannelFuture channelFuture = boot.connect(ip, port).sync();channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {@Overridepublic void operationComplete(Future<? super Void> future)throws Exception {if(future.isSuccess()){System.out.println('客戶端啟動中...');}if(future.isDone()){System.out.println('客戶端啟動成功...OK!');}}});System.out.println(channelFuture.channel().localAddress().toString());System.out.println('#################################################');System.out.println('~~~~~~~~~~~~~~端口號#消息內容~~這樣可以給單獨一個用戶發消息~~~~~~~~~~~~~~~~~~');System.out.println('#################################################');/** * 這里用控制臺輸入數據 */Channel channel = channelFuture.channel();//獲取channelScanner scanner = new Scanner(System.in);while(scanner.hasNextLine()){String str = scanner.nextLine();channel.writeAndFlush(str+'n');}channelFuture.channel().closeFuture().sync();scanner.close();} finally {work.shutdownGracefully();}}/** * 主方法入口 * @param args * @throws Exception */public static void main(String[] args) throws Exception{new NettyChatClient('127.0.0.1',9090).init();}}

客戶端消息處理Handler

package nio.test.netty.groupChat;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;/** * 客戶點消息處理 Handler * @author zhang * */public class ClientMessageHandler extends SimpleChannelInboundHandler<String> {/** * 處理收到的消息 */@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg)throws Exception {System.out.println(msg);}/** * 連接異常后觸發 */@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {ctx.close();}}

測試結果

啟動了四個客戶端 服務器端日志效果如下:

JAVA Netty實現聊天室+私聊功能的示例代碼

客戶端一端日志:

JAVA Netty實現聊天室+私聊功能的示例代碼

客戶端二日志:

JAVA Netty實現聊天室+私聊功能的示例代碼

客戶端三日志:

JAVA Netty實現聊天室+私聊功能的示例代碼

客戶端四日志:

JAVA Netty實現聊天室+私聊功能的示例代碼

現在在客戶端四發送消息:

JAVA Netty實現聊天室+私聊功能的示例代碼

每個客戶端都可以收到消息:

JAVA Netty實現聊天室+私聊功能的示例代碼

JAVA Netty實現聊天室+私聊功能的示例代碼

JAVA Netty實現聊天室+私聊功能的示例代碼

軟化關閉客戶端客戶端三:

服務器日志:

JAVA Netty實現聊天室+私聊功能的示例代碼

其他客戶端日志:

JAVA Netty實現聊天室+私聊功能的示例代碼

JAVA Netty實現聊天室+私聊功能的示例代碼

JAVA Netty實現聊天室+私聊功能的示例代碼

發送私聊消息:

JAVA Netty實現聊天室+私聊功能的示例代碼

這個客戶端收不到消息

JAVA Netty實現聊天室+私聊功能的示例代碼

JAVA Netty實現聊天室+私聊功能的示例代碼

到此這篇關于JAVA Netty實現聊天室+私聊功能的示例代碼的文章就介紹到這了,更多相關JAVA Netty聊天室內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 青州搬家公司电话_青州搬家公司哪家好「鸿喜」青州搬家 | 无尘烘箱_洁净烤箱_真空无氧烤箱_半导体烤箱_电子防潮柜-深圳市怡和兴机电 | 卫生型双针压力表-高温防腐差压表-安徽康泰电气有限公司 | 纸张环压仪-纸张平滑度仪-杭州纸邦自动化技术有限公司 | 潜水搅拌机-双曲面搅拌机-潜水推进器|奥伯尔环保 | 锡膏喷印机-全自动涂覆机厂家-全自动点胶机-视觉点胶机-深圳市博明智控科技有限公司 | 玻璃瓶厂家_酱菜瓶厂家_饮料瓶厂家_酒瓶厂家_玻璃杯厂家_徐州东明玻璃制品有限公司 | 卸料器-卸灰阀-卸料阀-瑞安市天蓝环保设备有限公司 | 断桥铝破碎机_铝合金破碎机_废铁金属破碎机-河南鑫世昌机械制造有限公司 | 干洗加盟网-洗衣店品牌排行-干洗设备价格-干洗连锁加盟指南 | 低合金板|安阳低合金板|河南低合金板|高强度板|桥梁板_安阳润兴 北京租车牌|京牌指标租赁|小客车指标出租 | 耐磨陶瓷,耐磨陶瓷管道_厂家-淄博拓创陶瓷科技 | 裹包机|裹膜机|缠膜机|绕膜机-上海晏陵智能设备有限公司 | 安徽集装箱厂-合肥国彩钢结构板房工程有限公司 | 航拍_专业的无人机航拍摄影门户社区网站_航拍网 | 国产频谱分析仪-国产网络分析仪-上海坚融实业有限公司 | 渣油泵,KCB齿轮泵,不锈钢齿轮泵,重油泵,煤焦油泵,泊头市泰邦泵阀制造有限公司 | 不锈钢复合板|钛复合板|金属复合板|南钢集团安徽金元素复合材料有限公司-官网 | 天津货架厂_穿梭车货架_重型仓储货架_阁楼货架定制-天津钢力仓储货架生产厂家_天津钢力智能仓储装备 | 谷梁科技| 彼得逊采泥器-定深式采泥器-电动土壤采样器-土壤样品风干机-常州索奥仪器制造有限公司 | 电气控制系统集成商-PLC控制柜变频控制柜-非标自动化定制-电气控制柜成套-NIDEC CT变频器-威肯自动化控制 | 上海瑶恒实业有限公司|消防泵泵|离心泵|官网 | 无线联网门锁|校园联网门锁|学校智能门锁|公租房智能门锁|保障房管理系统-KEENZY中科易安 | 杰恒蠕动泵-蠕动泵专业厂家-19年专注蠕动泵 | 高效节能电机_伺服主轴电机_铜转子电机_交流感应伺服电机_图片_型号_江苏智马科技有限公司 | 志高装潢官网-苏州老房旧房装修改造-二手房装修翻新 | 骨灰存放架|骨灰盒寄存架|骨灰架厂家|智慧殡葬|公墓陵园管理系统|网上祭奠|告别厅智能化-厦门慈愿科技 | 耐高温硅酸铝板-硅酸铝棉保温施工|亿欧建设工程 | 镀锌角钢_槽钢_扁钢_圆钢_方矩管厂家_镀锌花纹板-海邦钢铁(天津)有限公司 | 济南轻型钢结构/济南铁艺护栏/济南铁艺大门-济南燕翔铁艺制品有限公司 | 氢氧化钙设备_厂家-淄博工贸有限公司| 耐高温风管_耐高温软管_食品级软管_吸尘管_钢丝软管_卫生级软管_塑料波纹管-东莞市鑫翔宇软管有限公司 | 裹包机|裹膜机|缠膜机|绕膜机-上海晏陵智能设备有限公司 | 济南铝方通-济南铝方通价格-济南方通厂家-山东鲁方通建材有限公司 | 希望影视-高清影视vip热播电影电视剧免费在线抢先看 | 半自动预灌装机,卡式瓶灌装机,注射器灌装机,给药器灌装机,大输液灌装机,西林瓶灌装机-长沙一星制药机械有限公司 | 防堵吹扫装置-防堵风压测量装置-电动操作显示器-兴洲仪器 | 制氮设备_PSA制氮机_激光切割制氮机_氮气机生产厂家-苏州西斯气体设备有限公司 | 立式壁挂广告机厂家-红外电容触摸一体机价格-华邦瀛 | 台湾阳明固态继电器-奥托尼克斯光电传感器-接近开关-温控器-光纤传感器-编码器一级代理商江苏用之宜电气 |