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

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

Java實現NIO聊天室的示例代碼(群聊+私聊)

瀏覽:4日期:2022-08-12 18:38:18
功能介紹

功能:群聊+私發+上線提醒+下線提醒+查詢在線用戶

Java實現NIO聊天室的示例代碼(群聊+私聊)

Java實現NIO聊天室的示例代碼(群聊+私聊)

Java實現NIO聊天室的示例代碼(群聊+私聊)

Java實現NIO聊天室的示例代碼(群聊+私聊)

文件Utils

需要用maven導入下面兩個包

<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version></dependency><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version></dependency>

package moremorechat_nio;import lombok.extern.slf4j.Slf4j;import java.io.*;/** * @author mazouri * @create 2021-05-09 22:26 */@Slf4jpublic class Utils { /** * 將二進制數據轉為對象 * * @param buf * @return * @throws IOException * @throws ClassNotFoundException */ public static Message decode(byte[] buf) throws IOException, ClassNotFoundException {ByteArrayInputStream bais = new ByteArrayInputStream(buf);ObjectInputStream ois = new ObjectInputStream(bais);return (Message) ois.readObject(); } /** * 將對象轉為二進制數據 * * @param message * @return */ public static byte[] encode(Message message) throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(message);oos.flush();return baos.toByteArray(); }}FinalValue

package moremorechat_nio;/** * @author mazouri * @create 2021-05-05 21:00 */public final class FinalValue { /** * 系統消息 */ public static final int MSG_SYSTEM = 0; /** * 群發消息 */ public static final int MSG_GROUP = 1; /** * 私發消息 */ public static final int MSG_PRIVATE = 2; /** * 客戶端請求在線人員 */ public static final int MSG_ONLINE = 3; /** * 客戶端將用戶名稱發送給服務端 */ public static final int MSG_NAME = 4;}Message

package moremorechat_nio;import java.io.Serializable;/** * @author mazouri * @create 2021-05-05 21:00 */public class Message implements Serializable { public int type; public String message; public Message() { } public Message(String message) {this.message = message; } public Message(int type, String message) {this.type = type;this.message = message; } @Override public String toString() {return 'Message{' +'type=' + type +', message=’' + message + ’’’ +’}’; }}NioServer

package moremorechat_nio;import lombok.extern.slf4j.Slf4j;import java.io.*;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.ArrayList;import java.util.Iterator;import java.util.Set;import java.util.concurrent.atomic.AtomicBoolean;import java.util.stream.Collectors;import static moremorechat_nio.FinalValue.*;/** * ctrl+f12 方法 * ctrl+alt+左鍵 * @author mazouri * @create 2021-05-09 19:24 */@Slf4jpublic class NioServer { private Selector selector; private ServerSocketChannel ssc; public NioServer() {try { // 創建 selector, 管理多個 channel selector = Selector.open(); //打開ServerSocketChannel,用于監聽客戶端的連接,它是所有客戶端連接的父通道 ssc = ServerSocketChannel.open(); ssc.bind(new InetSocketAddress(8888)); //設置連接為非堵塞模式 ssc.configureBlocking(false); // 2. 建立 selector 和 channel 的聯系(注冊) // SelectionKey 就是將來事件發生后,通過它可以知道事件和哪個channel的事件 //將ServerSocketChannel注冊到Reactor線程的多路復用器Selector上,監聽ACCEPT事件 ssc.register(selector, SelectionKey.OP_ACCEPT);} catch (IOException e) { e.printStackTrace();} } public static void main(String[] args) {NioServer server = new NioServer();log.debug('server啟動完成,等待用戶連接...');try { server.listen();} catch (Exception e) { log.debug('發生了一些問題');} } /** * 監聽用戶的連接 * * @throws Exception */ private void listen() throws Exception {while (true) { // select 方法, 沒有事件發生,線程阻塞,有事件,線程才會恢復運行, 通過Selector的select()方法可以選擇已經準備就緒的通道 (這些通道包含你感興趣的的事件) //通過Selector的select()方法可以選擇已經準備就緒的通道 (這些通道包含你感興趣的的事件) // select 在事件未處理時,它不會阻塞, 事件發生后要么處理,要么取消,不能置之不理 selector.select(); // 處理事件, selectedKeys 內部包含了所有發生的事件 Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) {SelectionKey key = iterator.next();// 處理key 時,要從 selectedKeys 集合中刪除,否則下次處理就會有問題iterator.remove();// 區分事件類型if (key.isAcceptable()) { ServerSocketChannel channel = (ServerSocketChannel) key.channel(); SocketChannel sc = channel.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) { dealReadEvent(key);} }} } /** * 處理讀事件 * * @param key */ private void dealReadEvent(SelectionKey key) {SocketChannel channel = null;try { channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int read = channel.read(buffer); // 如果是正常斷開,read 的方法的返回值是 -1 if (read == -1) {//cancel 會取消注冊在 selector 上的 channel,并從 keys 集合中刪除 key 后續不會再監聽事件key.cancel(); } else {buffer.flip();Message msg = Utils.decode(buffer.array());log.debug(msg.toString());dealMessage(msg, key, channel); }} catch (IOException | ClassNotFoundException e) { System.out.println((key.attachment() == null ? '匿名用戶' : key.attachment()) + ' 離線了..'); dealMessage(new Message(MSG_SYSTEM, key.attachment() + ' 離線了..'), key, channel); //取消注冊 key.cancel(); //關閉通道 try {channel.close(); } catch (IOException ioException) {ioException.printStackTrace(); }} } /** * 處理各種消息,并發送給客戶端 * * @param msg * @param key * @param channel */ private void dealMessage(Message msg, SelectionKey key, SocketChannel channel) {switch (msg.type) { case MSG_NAME:key.attach(msg.message);log.debug('用戶{}已上線', msg.message);getConnectedChannel(channel).forEach(selectionKey -> { SocketChannel sc = (SocketChannel) selectionKey.channel(); sendMsgToClient(new Message('收到一條系統消息: ' + msg.message + '已上線'), sc);});break; case MSG_GROUP:getConnectedChannel(channel).forEach(selectionKey -> { SocketChannel sc = (SocketChannel) selectionKey.channel(); sendMsgToClient(new Message(key.attachment() + '給大家發送了一條消息: ' + msg.message), sc);});break; case MSG_PRIVATE:String[] s = msg.message.split('_');AtomicBoolean flag = new AtomicBoolean(false);getConnectedChannel(channel).stream().filter(sk -> s[0].equals(sk.attachment())).forEach(selectionKey -> { SocketChannel sc = (SocketChannel) selectionKey.channel(); sendMsgToClient(new Message(key.attachment() + '給你發送了一條消息: ' + s[1]), sc); flag.set(true);});if (!flag.get()){ sendMsgToClient(new Message(s[1]+'用戶不存在,請重新輸入!!!'), channel);}break; case MSG_ONLINE:ArrayList<String> onlineList = new ArrayList<>();onlineList.add((String) key.attachment());getConnectedChannel(channel).forEach(selectionKey -> onlineList.add((String) selectionKey.attachment()));sendMsgToClient(new Message(onlineList.toString()), channel);break; case MSG_SYSTEM:getConnectedChannel(channel).forEach(selectionKey -> { SocketChannel sc = (SocketChannel) selectionKey.channel(); sendMsgToClient(new Message('收到一條系統消息: ' + msg.message), sc);});break; default:break;} } /** * 發送消息給客戶端 * * @param msg * @param sc */ private void sendMsgToClient(Message msg, SocketChannel sc) {try { byte[] bytes = Utils.encode(msg); sc.write(ByteBuffer.wrap(bytes));} catch (IOException e) { log.debug('sendMsgToClient出現了一些問題');} } /** * 獲取所有channel,除去調用者 * * @param channel * @return */ private Set<SelectionKey> getConnectedChannel(SocketChannel channel) {return selector.keys().stream().filter(item -> item.channel() instanceof SocketChannel && item.channel().isOpen() && item.channel() != channel).collect(Collectors.toSet()); }}NioClient

package moremorechat_nio;import lombok.extern.slf4j.Slf4j;import java.io.*;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Scanner;import static moremorechat_nio.FinalValue.*;/** * @author mazouri * @create 2021-04-29 12:02 */@Slf4jpublic class NioClient { private Selector selector; private SocketChannel socketChannel; private String username; private static Scanner input; public NioClient() throws IOException {selector = Selector.open();socketChannel = SocketChannel.open(new InetSocketAddress('127.0.0.1', 8888));socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);log.debug('client啟動完成......');log.debug('請輸入你的名字完成注冊');input = new Scanner(System.in);username = input.next();log.debug('歡迎{}來到聊天系統', username); } public static void main(String[] args) throws IOException {System.out.println('tips: n1. 直接發送消息會發給當前的所有用戶 n2. @用戶名:消息 會私發給你要發送的用戶 n3. 輸入 查詢在線用戶 會顯示當前的在線用戶');NioClient client = new NioClient();//啟動一個子線程接受服務器發送過來的消息new Thread(() -> { try {client.acceptMessageFromServer(); } catch (Exception e) {e.printStackTrace(); }}, 'receiveClientThread').start();//調用sendMessageToServer,發送消息到服務端client.sendMessageToServer(); } /** * 將消息發送到服務端 * * @throws IOException */ private void sendMessageToServer() throws IOException {//先把用戶名發給客戶端Message message = new Message(MSG_NAME, username);byte[] bytes = Utils.encode(message);socketChannel.write(ByteBuffer.wrap(bytes));while (input.hasNextLine()) { String msgStr = input.next(); Message msg; boolean isPrivate = msgStr.startsWith('@'); if (isPrivate) {int idx = msgStr.indexOf(':');String targetName = msgStr.substring(1, idx);msgStr = msgStr.substring(idx + 1);msg = new Message(MSG_PRIVATE, targetName + '_' + msgStr); } else if ('查詢在線用戶'.equals(msgStr)) {msg = new Message(MSG_ONLINE, '請求在線人數'); } else {msg = new Message(MSG_GROUP, msgStr); } byte[] bytes1 = Utils.encode(msg); socketChannel.write(ByteBuffer.wrap(bytes1));} } /** * 接受從服務器發送過來的消息 */ private void acceptMessageFromServer() throws Exception {while (selector.select() > 0) { Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) {SelectionKey key = iterator.next();iterator.remove();if (key.isReadable()) { SocketChannel sc = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); sc.read(buffer); Message message = Utils.decode(buffer.array()); log.debug(String.valueOf(message.message));} }} }}

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

標簽: Java
相關文章:
主站蜘蛛池模板: 钢化玻璃膜|手机钢化膜|钢化膜厂家|手机保护膜-【东莞市大象电子科技有限公司】 | 数码管_LED贴片灯_LED数码管厂家-无锡市冠卓电子科技有限公司 | 瑞典Blueair空气净化器租赁服务中心-专注新装修办公室除醛去异味服务! | 无菌检查集菌仪,微生物限度仪器-苏州长留仪器百科 | 山东锐智科电检测仪器有限公司_超声波测厚仪,涂层测厚仪,里氏硬度计,电火花检漏仪,地下管线探测仪 | 河南卓美创业科技有限公司-河南卓美防雷公司-防雷接地-防雷工程-重庆避雷针-避雷器-防雷检测-避雷带-避雷针-避雷塔、机房防雷、古建筑防雷等-山西防雷公司 | 对辊式破碎机-对辊制砂机-双辊-双齿辊破碎机-巩义市裕顺机械制造有限公司 | 山东风淋室_201/304不锈钢风淋室净化设备厂家-盛之源风淋室厂家 翻斗式矿车|固定式矿车|曲轨侧卸式矿车|梭式矿车|矿车配件-山东卓力矿车生产厂家 | 苏州防水公司_厂房屋面外墙防水_地下室卫生间防水堵漏-苏州伊诺尔防水工程有限公司 | 水厂自动化-水厂控制系统-泵站自动化|控制系统-闸门自动化控制-济南华通中控科技有限公司 | 电镀电源整流器_高频电解电源_单脉双脉冲电源 - 东阳市旭东电子科技 | 单级/双级旋片式真空泵厂家,2xz旋片真空泵-浙江台州求精真空泵有限公司 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 浇钢砖,流钢砖_厂家价低-淄博恒森耐火材料有限公司 | 精密模具制造,注塑加工,吹塑和吹瓶加工,EPS泡沫包装生产 - 济南兴田塑胶有限公司 | 中国产业发展研究网 - 提供行业研究报告 可行性研究报告 投资咨询 市场调研服务 | 合肥抖音SEO网站优化-网站建设-网络推广营销公司-百度爱采购-安徽企匠科技 | 杭州翻译公司_驾照翻译_专业人工翻译-杭州以琳翻译有限公司官网 组织研磨机-高通量组织研磨仪-实验室多样品组织研磨机-东方天净 | 登车桥动力单元-非标液压泵站-非标液压系统-深圳市三好科技有限公司 | 数显恒温培养摇床-卧式/台式恒温培养摇床|朗越仪器 | 特种阀门-调节阀门-高温熔盐阀-镍合金截止阀-钛阀门-高温阀门-高性能蝶阀-蒙乃尔合金阀门-福建捷斯特阀门制造有限公司 | 油罐车_加油机_加油卷盘_加油机卷盘_罐车人孔盖_各类球阀_海底阀等车用配件厂家-湖北华特专用设备有限公司 | 上海公司注册-代理记账-招投标审计-上海昆仑扇财税咨询有限公司 上海冠顶工业设备有限公司-隧道炉,烘箱,UV固化机,涂装设备,高温炉,工业机器人生产厂家 | 潜水搅拌机-双曲面搅拌机-潜水推进器|奥伯尔环保 | 石英砂矿石色选机_履带辣椒色选机_X光异物检测机-合肥幼狮光电科技 | 冷藏车-东风吸污车-纯电动环卫车-污水净化车-应急特勤保障车-程力专汽厂家-程力专用汽车股份有限公司销售二十一分公司 | 碳钢法兰厂家,非标法兰,定制异型,法兰生产厂家-河北九瑞管道 | 快速卷帘门_硬质快速卷帘门-西朗门业 | 中视电广_短视频拍摄_短视频推广_短视频代运营_宣传片拍摄_影视广告制作_中视电广 | 预制舱-电力集装箱预制舱-模块化预制舱生产厂家-腾达电器设备 | 自动螺旋上料机厂家价格-斗式提升机定制-螺杆绞龙输送机-杰凯上料机 | 垃圾处理设备_餐厨垃圾处理设备_厨余垃圾处理设备_果蔬垃圾处理设备-深圳市三盛环保科技有限公司 | 亿立分板机_曲线_锯片式_走刀_在线式全自动_铣刀_在线V槽分板机-杭州亿协智能装备有限公司 | ALC墙板_ALC轻质隔墙板_隔音防火墙板_轻质隔墙材料-湖北博悦佳 | 深圳宣传片制作_产品视频制作_深圳3D动画制作公司_深圳短视频拍摄-深圳市西典映画传媒有限公司 | 绿萝净除甲醛|深圳除甲醛公司|测甲醛怎么收费|培训机构|电影院|办公室|车内|室内除甲醛案例|原理|方法|价格立马咨询 | 新疆系统集成_新疆系统集成公司_系统集成项目-新疆利成科技 | 西装定制/做厂家/公司_西装订做/制价格/费用-北京圣达信西装 | 山东限矩型液力偶合器_液力耦合器易熔塞厂家-淄博市汇川源机械厂 | 北京征地律师,征地拆迁律师,专业拆迁律师,北京拆迁律师,征地纠纷律师,征地诉讼律师,征地拆迁补偿,拆迁律师 - 北京凯诺律师事务所 | 扒渣机,铁水扒渣机,钢水扒渣机,铁水捞渣机,钢水捞渣机-烟台盛利达工程技术有限公司 |