mina实现联网----多功能聊天室

tech2026-08-30  1

聊天室简介

聊天室使用mina完成,用户打开客户端连接服务器,随即在控制台输入并得到信息。将私聊与群聊使用集合存入数据进行判断然后给予信息反馈,群聊时可@全体成员或任意人员,私聊#与@不能同时进行,聊天室将进行友好的提示,帮助用户更好的了解操作的方法。 -----------由于控制台输入,有些问题无法避免,请见谅-----------

jar包环境配置

使用mina进行聊天室的建立,需要的jar包有:

commons-logging-1.0.3.jar mina-core-2.1.3.jar slf4j-api-1.7.26.jar

聊天室展示

测试1:

测试2:

客户端类

用户打开客户端后输入名字后验证是否存在,此时主线程进行睡眠状态,当验证成功时子线程将打断主线程睡眠,群体广播提示登录聊天室,进行群聊时可以私聊他人,秘密你我共知。群聊时@他人,系统将给予此人相应的提示,@和#用户时请按指示使用,输入错误给予提示。。。退出登录时,系统广播给予提示。

package chat; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.Scanner; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketConnector; public class MinaClient { public static String name = ""; public static void main(String[] args) { // TODO Auto-generated method stub MinaClient mc = new MinaClient(); //创建IoService实例 NioSocketConnector connector = new NioSocketConnector(); //2,设置过滤链 日志、编解码 //通过连接器获得当前的过滤链对象 connector.getFilterChain().addLast("logger", new LoggingFilter()); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName("UTF-8")))); Thread t = Thread.currentThread(); //3,绑定IO处理器,传入当前线程用于唤醒 connector.setHandler(new MinaClientHandler(t)); //连接地址 ConnectFuture connect = connector.connect(new InetSocketAddress("localhost",8888)); System.out.println("客户端连接成功!!"); Scanner scan = new Scanner(System.in); //用户开启客户端,输入属于自己的名称 do { if(MinaClient.name.contains(":")) { System.out.println("昵称中不能包含:,请重新输入"); }else { System.out.println("请输入昵称?"); } MinaClient. name = scan.next(); }while(MinaClient.name.contains(":")); //从连接对象中获得当前的会话对象 IoSession session = connect.getSession(); //服务器未开启时为空 if(session==null) { System.out.println("服务器未开启,请等待服务器开启再进入···"); System.exit(0); } //传给服务器名字 session.write(MinaClient.name); //睡眠,等待输入正确名字后唤醒 try { t.sleep(1000000000000L); } catch (InterruptedException e) { // TODO Auto-generated catch block } int count = 0; //eclipse中文输入中文在其他行时会把汉字敲打的字母打印 System.out.println("\t·····为了用户体验,请eclipse用户输入中文前请将光标移动到最后一行(无文字行)·····"); while(true) { //开始聊天 System.out.println("--私聊 # 和艾特 @ 请在名字后加一个空格- -"); String content = scan.nextLine(); if(count==0) { count++; session.write(MinaClient.name+":已进入聊天室~~~~~~~~~~~~~~"); } //输入姓名后自动执行了一次输入空白 if("".equals(content)&&count!=1) { System.out.println("········不能输入空白信息,请重新输入"); }else if(content.contains("@")&&content.contains("#")) { System.out.println("········不能#并@,请重新输入"); }else { session.write(MinaClient.name+":"+content); } try { t.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } class MinaClientHandler extends IoHandlerAdapter { Thread t ; public MinaClientHandler(Thread t) { super(); this.t = t; } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { // TODO Auto-generated method stub System.out.println("client异常提示"); super.exceptionCaught(session, cause); } @Override public void inputClosed(IoSession session) throws Exception { // TODO Auto-generated method stub System.out.println("client关闭:"+session); super.inputClosed(session); } @Override public void messageReceived(IoSession session, Object message) throws Exception { // TODO Auto-generated method stub //打印数据 //判断登录成功时唤醒主线程 if(message.equals(MinaClient.name+"登录成功")) { t.interrupt(); } System.out.println("\n"+message); //当用户名重复时提示并使用户重新输入 if(message.equals(MinaClient.name+"已存在,请重新登录")) { System.out.println("请重新输入昵称"); Scanner scan = new Scanner(System.in); MinaClient. name = scan.next(); session.write(MinaClient.name); } super.messageReceived(session, message); } @Override public void messageSent(IoSession session, Object message) throws Exception { // TODO Auto-generated method stub //System.out.println("client发送消息:"+message); super.messageSent(session, message); } @Override public void sessionClosed(IoSession session) throws Exception { // TODO Auto-generated method stub System.out.println("client当前会话关闭"); System.exit(0); super.sessionClosed(session); } @Override public void sessionCreated(IoSession session) throws Exception { // TODO Auto-generated method stub //System.out.println("client会话被新创建..."); super.sessionCreated(session); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { // TODO Auto-generated method stub //System.out.println("client会话休眠中"); super.sessionIdle(session, status); } }

实体类

保存登录用户的信息,在服务类中提供业务判断和信息修改

class MySession { private IoSession session;//同ID private String name;//姓名 private int state;// 状态,1 登录或 0 未登录 public MySession(IoSession session, int state) { super(); this.session = session; this.state = state; } public IoSession getSession() { return session; } public void setSession(IoSession session) { this.session = session; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getState() { return state; } public void setState(int state) { this.state = state; } @Override public boolean equals(Object arg0) { // TODO Auto-generated method stub MySession temp = (MySession) arg0; if (name.equals(temp.getName())) { return true; } return super.equals(arg0); } @Override public int hashCode() { // TODO Auto-generated method stub return name.hashCode(); } }

服务端类

客户端连接时赋给实体类登录状态为0并存入未登录状态集合中,当判断名字不存在时改为1存入登录状态集合,名字存在即进入0对应的业务代码块。用户进入此类判断是否为第一次输入名字,修改实体类信息。 @与#拥有aimChat方法与singleChat,群聊有boradCast,退出有exitChat进行业务处理。

package chat; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Vector; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.service.IoService; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaServer { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub // 1,创建IoService的实例 IoAcceptor acceptor = new NioSocketAcceptor(); // 2,设置过滤链 日志、编解码 // 通过接收器获得当前的过滤链对象 acceptor.getFilterChain().addLast("logger", new LoggingFilter()); acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); // 3,绑定IO处理器 acceptor.setHandler(new MyServerHandler()); // 4,监听端口 acceptor.bind(new InetSocketAddress(8888)); System.out.println("服务端启动,并监听端口:8888"); } } class MyServerHandler extends IoHandlerAdapter { // 连接却未登录状态的客户端 private Vector<MySession> vms = new Vector<MySession>(); // 连接且登录状态的客户端 private LinkedHashSet<MySession> sessions = new LinkedHashSet<MySession>(); @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { // TODO Auto-generated method stub // 断开连接后为false // 客户端断开,集合移除该用户 if (!session.isConnected()) { exitChat(session); } super.exceptionCaught(session, cause); } @Override public void inputClosed(IoSession session) throws Exception { // TODO Auto-generated method stub System.out.println("服务端关闭:" + session); super.inputClosed(session); } @Override public void messageReceived(IoSession session, Object message) throws Exception { // TODO Auto-generated method stub // 第一步,获得数据 System.out.println(message); MySession ms = null; // 将第一次进入客户端数据赋值给ms,第二次进入方法时登录状态已经改变。 for (MySession mySession : vms) { if (mySession.getSession() == session) { ms = mySession; } } // 第二步,解析自定义的协议,解析出来发送者、内容、接收者 // 清除名字包含的空格 String data = ((String) message).trim(); int first = data.indexOf(":"); String name = ""; // 用户的名字,客户端发送信息一定会带:,为-1一定是输入名字时 if (first == -1) { name = data; ms.setName(name); } // 用户发送的信息,一次接收一行,空白不会接收,也不会从客户端发送过来 String msg = null; if (data.contains(":")) { msg = data.substring(first + 1); } // 第三步,判定该session是否已连接,并且是第一次发送数据 if (!sessions.contains(ms)) { sessions.add(ms); ms.getSession().write(ms.getName() + "登录成功"); System.out.println(ms.getName() + "已成功登录"); // 改变用户状态 ms.setState(1); } // 未登录状态验证名字是否重复 if (ms.getState() == 0) { Iterator<MySession> iterator = sessions.iterator(); while (iterator.hasNext()) { MySession ms2 = iterator.next(); if (ms.getName().equals(ms2.getName())) { ms.getSession().write(ms.getName() + "已存在,请重新登录"); } } } if (msg != null && !msg.equals("")) { // 第四步,选择私聊对象 if (msg.contains("@")) { aimChat(ms, msg); } else if (msg.contains("#")) { singleChat(ms, msg); } else { boradCast(ms, msg); } } super.messageReceived(session, message); } /* * 将数据发给所有用户 */ private void boradCast(MySession ms, String msg) { System.out.println("开始广播"); for (MySession ms2 : sessions) { ms2.getSession().write(ms.getName() + ":" + msg); } } /* * 1,当前的session对象和发送者 2,当前发送的内容 给被@的人提供提示 */ private void aimChat(MySession ms, String msg) { boolean flag = false; if (msg.contains("@全体成员 ") || msg.endsWith("@全体成员")) { for (MySession msTemp : sessions) { flag = true; // @除自己外所有人 if (ms.getSession() != msTemp.getSession()) { msTemp.getSession().write("@有人艾特你:\n" + ms.getName() + ":" + msg); } } ms.getSession().write(ms.getName() + ":" + msg); } else { for (MySession msTemp : sessions) { // 没有被@的人收到信息不提示 if (!msg.contains("@" + msTemp.getName() + " ") && !msg.endsWith("@" + msTemp.getName())) { msTemp.getSession().write(ms.getName() + ":" + msg); } else if (ms.getSession() != msTemp.getSession()) { // 有目标对象时改为true,不进行无提示广播 flag = true; // 提示被@用户.并将内容发送 msTemp.getSession().write("@有人艾特你:\n" + ms.getName() + ":" + msg); } else { flag = true; ms.getSession().write("\t\t\t\t!!!!!请不要艾特自己!!!!!!"); } } } // 找不到@的对象,广播信息 if (!flag) { System.out.println("@转广播"); ms.getSession().write("\t\t\t\t!!!!!未找到@对象!!!!!!"); } } /* * 私聊指定用户 */ private void singleChat(MySession ms, String msg) { String targetName = ""; String content = ""; boolean flag = false; System.out.println("开始私聊"); if (msg.contains("#" + ms.getName() + " ")) { ms.getSession().write("\t\t\t\t!!!!!请不要私聊自己!!!!!!"); } else { for (MySession msTemp : sessions) { // 如果私聊该对象,进行局部变量状态改变 if (msg.contains("#" + msTemp.getName() + " ") || msg.endsWith("#" + msTemp.getName())) { flag = true; targetName = msTemp.getName(); content = msg.replace("#" + targetName, ""); // 找到接收者session.并将内容发送 msTemp.getSession().write(ms.getName() + "悄悄对你说:" + content); } } if (!flag) { // 没有找到私聊的对象 ms.getSession().write("\t\t\t\t!!!!!没有你要找的人!!!!!!"); } else { ms.getSession().write("你偷偷对" + targetName + "说:" + content); } } } /* * 退出程序提示 */ private void exitChat(IoSession session) { Iterator<MySession> iterator = sessions.iterator(); while (iterator.hasNext()) { MySession ms = iterator.next(); if (ms.getSession() == session) { sessions.remove(ms); vms.remove(ms); // TODO Auto-generated method stub boradCast(ms, ms.getName() + "已退出聊天室~~~~~~~~~~~~~~"); } } } @Override public void messageSent(IoSession session, Object message) throws Exception { // TODO Auto-generated method stub System.out.println("服务端 发送消息:" + message); super.messageSent(session, message); } @Override public void sessionClosed(IoSession session) throws Exception { exitChat(session); super.sessionClosed(session); } @Override public void sessionCreated(IoSession session) throws Exception { // TODO Auto-generated method stub System.out.println("服务端 会话被新创建..."); // 用户连接,存入集合 MySession ms = new MySession(session, 0); vms.add(ms); super.sessionCreated(session); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { // TODO Auto-generated method stub System.out.println("服务端 会话休眠中"); super.sessionIdle(session, status); } } class MySession { private IoSession session; private String name; private int state;// 状态,1 登录或 0 未登录 public MySession(IoSession session, int state) { super(); this.session = session; this.state = state; } public IoSession getSession() { return session; } public void setSession(IoSession session) { this.session = session; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getState() { return state; } public void setState(int state) { this.state = state; } @Override public boolean equals(Object arg0) { // TODO Auto-generated method stub MySession temp = (MySession) arg0; if (name.equals(temp.getName())) { return true; } return super.equals(arg0); } @Override public int hashCode() { // TODO Auto-generated method stub return name.hashCode(); } }
最新回复(0)