Java使用TCP实现聊天室系统
2020-02-07 06:07
190 查看
目标功能:
1.群聊
2.退出
3.私聊
4.查询其他在线玩家
5.管理员登陆
6.踢人
7.禁言
目前已实现四个功能
如何使用?
1 先启动服务端程序,再启动客户端
2 输入昵称后才能连接服务端
3 输入内容后回车即可发送群聊消息
3 输入 ls 查询在线玩家
4 输入 @要私聊对象的名字:要私聊的信息 即可实现私聊
5 输入 exit 即可退出聊天室
服务器
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class Server { //用该容器存储与用户建立的连接 static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<>(); List<String> list = new ArrayList(); //以下两个常量用来区分 系统和用户 private final static boolean system = true; private final static boolean user = false; public static void main(String[] args) throws IOException { //创建服务端 ServerSocket server = new ServerSocket(8888); System.out.println("服务端建立完毕,端口号:" + server.getLocalPort()); //准备连接 Channel c; //接受客户端 while (true){ //监听到连接后,为该客户端开辟一个线程 Socket client = server.accept(); c = new Channel(client); new Thread(c).start(); //加入到容器中 all.add(c); System.out.println("玩家:"+c.name+ " 已连接上..."); } } //通信管道,一个用户对应一个管道(内部类),封装了流和用户信息 static class Channel implements Runnable{ private Socket client; private DataInputStream dis; private DataOutputStream dos; private boolean isRunning; private String name; //此构造方法用来初始化流和用户昵称 public Channel(Socket client){ this.client = client; try { dis = new DataInputStream(client.getInputStream()); dos = new DataOutputStream(client.getOutputStream()); //默认处于连接状态,用于收发信息 isRunning = true; //初始化姓名 name = dis.readUTF(); //+1为包括自身 this.send("欢迎进入聊天室,当前在线玩家数: "+(all.size()+1)+"\r\n"+ "指令:ls(查询当前在线用户),@XX:YY(向玩家XX发送消息YY),exit(退出聊天室)"); }catch (IOException e) { System.out.println("初始化失败"); //释放资源 release(); } } //run方法循环转发用户消息 @Override public void run() { while (isRunning){ String msg = receive(client); if(!msg.equals("")){ if (msg.equals("exit")){//断开连接 System.out.println("玩家:"+this.name+" 已断开连接"); sendOthers(name+"退出了群聊",system);//告诉所有人 此人离开了 release(); break; }else if (msg.startsWith("@")){//私聊 int index = msg.indexOf(":"); if (index!= -1){ String targetName = msg.substring(1,index); sendTarget(msg,targetName); }else { sendTarget(msg,"error"); } }else if (msg.equals("ls")){//查询在线玩家 StringBuilder sb = searchOnline(); if (!sb.equals("]")) { this.send("当前在线的玩家:"+sb.toString()); } } else { sendOthers(name+"说:"+msg,user);//向所有人广播此消息,除了他自己 } } } } //接受信息 public String receive(Socket client) { String msg = ""; try { //阻塞,只有用户发送了信息,服务器才会接受并广播给其他用户 msg = dis.readUTF(); } catch (IOException e) { System.out.println("玩家:"+this.name+" 异常中断"); //非输入exit退出,同样需要广播此用户的退出 sendOthers(name+"退出了群聊",system);//告诉所有人 此人离开了 //客户端强制退出时,释放资源 release(); } return msg; } //广播的最底层操作是调用Channel中的send方法 public void send(String msg){ try { dos.writeUTF(msg); dos.flush(); }catch (IOException e){ System.out.println("信息传出异常,连接已断开"); release(); } } //广播,调用时确认是系统还是用户 public void sendOthers(String msg,boolean who){ if (msg!=""){ for (Channel c:all){ //任何消息不回反馈给发送者本身 if (c!=this) { if (who == system) { c.send("***系统消息: " + msg + "***"); } else {//用户 c.send(msg); } } } } } //私聊 public void sendTarget(String msg,String name){ boolean flag = true; for (Channel c:all){ if (c.name.equals(name)){ c.send(this.name+"悄悄地对你说:"+msg.substring(msg.indexOf(":")+1)); flag = false; break; } } if (flag){ System.out.println(flag); if (name.equals("error")){ this.send("指令错误,请输入英文状态下的冒号"); }else { this.send("***找不到该用户***"); } } } //查询其他在线的玩家 public StringBuilder searchOnline(){ StringBuilder sb = new StringBuilder("["); for (Channel c:all){ sb.append(c.name+","); } sb.setCharAt(sb.length()-1,']'); return sb; } //释放资源时从容器中剔除自身的引用(此Channel因各种原因断开),并关闭转发器(停止run方法中的while循环) private void release(){ this.isRunning = false; all.remove(this); System.out.println("剩余玩家"+all.size()); TianUtils.close(dis,dos,client); } } }
客户端
import java.io.*; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String[] args) throws IOException { //输入昵称后,再向服务器建立连接 System.out.print("请输入昵称:"); String name = new Scanner(System.in).nextLine(); //创建客户端 Socket client = new Socket("localhost",8888); /** * 用户应该能同时收发消息,所以需要用到多线程 * Sender为发送者线程 * Receiver为接收者线程 */ new Thread(new Sender(client,name)).start(); new Thread(new Receiver(client)).start(); } }
客户端子线程:发送者
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class Sender implements Runnable{ private Socket client; private DataOutputStream dos; private BufferedReader reader; //初始化流,并向服务器传递用户昵称,服务器在初始化链接(Channel)时接收昵称 public Sender(Socket client,String name){ this.client = client; try { dos = new DataOutputStream(client.getOutputStream()); reader = new BufferedReader(new InputStreamReader(System.in)); dos.writeUTF(name); } catch (IOException e) { System.out.println("初始化流失败"); release(); } } @Override public void run() { while (true){ try { String msg = reader.readLine(); if (msg.equals("exit")){ dos.writeUTF(msg);//输入exit主动断开连接 dos.flush(); break; } dos.writeUTF(msg); dos.flush(); } catch (IOException e) { System.out.println("发送异常"); release(); } } } //释放资源 private void release(){ TianUtils.close(client,dos,reader); } }
客户端子线程:接收者
import java.io.DataInputStream; import java.io.IOException; import java.net.Socket; public class Receiver implements Runnable{ private Socket client; private DataInputStream dis = null; //初始化流,用来接收服务器广播的消息 public Receiver(Socket client){ this.client = client; try { dis = new DataInputStream(client.getInputStream()); } catch (IOException e) { System.out.println("初始化失败"); release(); } } @Override public void run() { while (true){ try { //当输入exit时,此操作异常,run方法终止 System.out.println(dis.readUTF()); } catch (IOException e) { System.out.println("与服务器断开连接"); break; } } release(); } //释放资源 private void release(){ TianUtils.close(client,dis); } }
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 使用Silverlight4与Wcf4的Net.tcp实现的简单聊天室
- java网络编程,通过TCP,Socket实现多对一的局域网聊天室
- java中读写锁的实现及使用读写锁简单实现缓存系统的实例
- 基于Java的tcp实现文本聊天系统
- Java的图形化点菜系统(文件流、TCP及线程实现)
- Silverlight使用socket tcp简单实现聊天室功能
- 使用java基于pushlet和bootstrap实现的简单聊天室
- 使用java代码来实现dvd管理系统
- Java使用TCP实现数据传输实例详解
- 使用JAVA executor实现TCP 网络通讯
- java分布式开发TCP/IP NIO无阻塞 Socket((基于消息方式实现系统间的通信) )(转)
- java 实现系统目录树 ,树控件使用,显示 系统文件夹
- [分布式java]基于JavaAPI实现消息方式的系统间通信:TCP/IP+NIO
- Java使用socket网络编程实现多人聊天室
- Java——基于java自身包实现消息系统间的通信(TCP/IP+NIO)
- Java——基于java自身包实现消息系统间的通信(TCP/IP+NIO)
- java 使用TCP实现单聊的功能。(客户端和服务端聊天)
- 使用JAVA实现Socket通信,TCP、UDP简析。
- Java 网络编程(TCP)实现服务器与客户端1对多的随意顺 序的聊天室
- java使用MulticastSocket实现基于广播的多人聊天室