Java怎么用局域网实现聊天室功能
发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,这篇文章主要介绍了Java怎么用局域网实现聊天室功能的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java怎么用局域网实现聊天室功能文章都会有所收获,下面我们一起来看看吧
千家信息网最后更新 2025年02月05日Java怎么用局域网实现聊天室功能
这篇文章主要介绍了Java怎么用局域网实现聊天室功能的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java怎么用局域网实现聊天室功能文章都会有所收获,下面我们一起来看看吧。
类和接口
Server类(服务器端)
package Test;import java.io.IOException;import java.io.PrintStream;import java.net.ServerSocket;import java.net.Socket;public class Server { private static final int SERVER_PORT=30000; //使用CrazyitMap对象来保存每个客户名字和对应输出流之间的对应关系 public static CrazyitMapclients=new CrazyitMap<>(); public void init(){ try( //建立监听的ServerSocket ServerSocket ss=new ServerSocket(SERVER_PORT)) { //采用死循环来不断地接收来自客户端的请求 while(true){ Socket socket=ss.accept(); new ServerThread(socket).start(); } } //如果抛出异常 catch (IOException ex){ System.out.println("服务器启动失败,是否端口"+SERVER_PORT+"已被占用"); } } public static void main(String[] args){ Server server=new Server(); server.init(); }}
ServerThread类
package Test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;public class ServerThread extends Thread { private Socket socket; BufferedReader br = null; PrintStream ps = null; //定义一个构造器,用于接收一个Socket来创建ServerThread线程 public ServerThread(Socket socket) { this.socket = socket; } public void run() { try { //获取该Socket对应的输入流 br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取该Socket对应的输出流 ps = new PrintStream(socket.getOutputStream()); String line = null; while ((line = br.readLine()) != null) { //如果读到的行以CrazyitProtocol.USER_ROUND开始,并以其结束 //则可以确定读到的是用户登录的用户名 if (line.startsWith(CrazyitProtocol.USER_ROUND) && line.endsWith(CrazyitProtocol.USER_ROUND)) { //得到真实消息 String userName = getRealMsg(line); //如果用户名重复 if (Server.clients.map.containsKey(userName)) { System.out.println("重复"); ps.println(CrazyitProtocol.NAME_REP); } else { System.out.println("成功"); ps.println(CrazyitProtocol.LOGIN_SUCCESS); Server.clients.put(userName, ps); } } //如果读到的行以CrazyitProtocol.PRIVATE_ROUND开始, //则可以确定是私聊信息,私聊信息只向特定的输入流发送 else if (line.startsWith(CrazyitProtocol.PRIVATE_ROUND) && line.endsWith(CrazyitProtocol.PRIVATE_ROUND)) { //得到真实的消息 String userAndMsg = getRealMsg(line); //以SPLIT_SIGN分割字符串,前半是私聊用户,后半是聊天信息 String user = userAndMsg.split(CrazyitProtocol.SPLIT_SIGN)[0]; String msg = userAndMsg.split(CrazyitProtocol.SPLIT_SIGN)[1]; //获取私聊用户对应的输出流,并发送私聊信息 Server.clients.map.get(user).println(Server.clients.getKeyByValue(ps) + "悄悄对你说:" + msg); } //公聊要向每一个Socket发送 else { //得到真实消息 String msg = getRealMsg(line); //遍历clients中的每个输出流 for (PrintStream clientPs : Server.clients.valueSet()) { clientPs.println(Server.clients.getKeyByValue(ps) + "说:" + msg); } } } } //捕获到异常后,表明Socket对应的客户端已经出现了问题 //所以程序将其对应的输出流从Map中删除 catch (IOException e) { Server.clients.removeByValue(ps); System.out.println(Server.clients.map.size()); //关闭网络,IO资源 try { if (br != null) { br.close(); } if (ps != null) { ps.close(); } if (socket != null) { socket.close(); } } catch (IOException ex) { ex.printStackTrace(); } } } //将读到的内容去掉前后协议字符,恢复成真实数据 private String getRealMsg(String line) { return line.substring(CrazyitProtocol.PROTOCOL_LEN,line.length()-CrazyitProtocol.PROTOCOL_LEN); }}
Client类
package Test;import javax.swing.*;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;import java.net.UnknownHostException;public class Client { private static final int SERVER_PORT=30000; private Socket socket; private PrintStream ps; private BufferedReader brServer; private BufferedReader keyIn; public void init(){ try { //初始化代表键盘的输入流 keyIn=new BufferedReader(new InputStreamReader(System.in)); //连接到服务器端 socket=new Socket("127.0.0.1",SERVER_PORT); //获取该Socket对应的输入流和输出流 ps=new PrintStream(socket.getOutputStream()); brServer=new BufferedReader(new InputStreamReader(socket.getInputStream())); String tip=" "; //采用不断循环地弹出对话框要求输入用户名 while(true){ String userName= JOptionPane.showInputDialog(tip+"输入用户名"); //用户输入的用户名前后增加协议字符串后发送 ps.println(CrazyitProtocol.USER_ROUND+userName+CrazyitProtocol.USER_ROUND); //读取服务器端的响应 String result=brServer.readLine(); //如果用户名重复,则开始下一次循环 if (result.equals(CrazyitProtocol.NAME_REP)){ tip="用户名重复,请重试"; continue; } //服务器端登录成功 if (result.equals(CrazyitProtocol.LOGIN_SUCCESS)){ break; } } } //捕获到异常,关闭网络资源,并退出该程序 catch (UnknownHostException ex){ System.out.println("找不到远程服务器,请确定服务器已经启动"); closeRs(); System.exit(1); } catch(IOException ex){ System.out.println("网络异常,请重新登录"); closeRs(); System.exit(1); } //以该Socket对应的输入流启动ClientThread线程 new ClientThread(brServer).start(); } //定义一个读取键盘输出,并以网络发送的方法 private void readAndSend(){ try { //不断读取键盘输入 String line=null; while ((line=keyIn.readLine())!=null){ //如果发送的信号中有冒号,并以//开头,则认为想发送私聊信息 if (line.indexOf(":")>0&&line.startsWith("//")){ line=line.substring(2); ps.println(CrazyitProtocol.PRIVATE_ROUND+line.split(":")[0]+CrazyitProtocol.SPLIT_SIGN+line.split(":")[1]+CrazyitProtocol.PRIVATE_ROUND); } else{ ps.println(CrazyitProtocol.MSG_ROUND+line+CrazyitProtocol.MSG_ROUND); } } } catch (IOException ex){ System.out.println("网络通信异常!请重新登录"); closeRs(); System.exit(1); } } //关闭Socket,输入流,输出流的方法 private void closeRs(){ try { if (keyIn!=null){ ps.close(); } if (brServer!=null){ ps.close(); } if (ps!=null){ ps.close(); } if (socket!=null){ keyIn.close(); } } catch (IOException ex){ ex.printStackTrace(); } } public static void main(String[] args){ Client client=new Client(); client.init(); client.readAndSend(); }}
ClientThread类
package Test;import java.io.BufferedReader;import java.io.IOException;public class ClientThread extends Thread { //该客户端线程负责处理输入流 BufferedReader br=null; //使用一个网络输入流来创建客户端线程 public ClientThread(BufferedReader br){ this.br=br; } public void run(){ try { String line=null; //不断地从输入流中读取数据,并将这些数据打印输出 while((line=br.readLine())!=null){ System.out.println(line); } } catch (IOException ex){ ex.printStackTrace(); } finally { try { if (br!=null){ br.close(); } } catch (IOException ex){ ex.printStackTrace(); } } }}
CrazyitMap类
package Test;import java.util.*;public class CrazyitMap{ //创建一个线程安全的HashMap public Map map= Collections.synchronizedMap(new HashMap ()); //根据value来删除指定项 public synchronized void removeByValue(Object value){ for (Object key:map.keySet()){ if (map.get(key)==value){ map.remove(key); break; } } } //获取所有value组成的Set集合 public synchronized Set valueSet(){ Set result=new HashSet (); //将map中的所有value添加到result集合中 map.forEach((key,value)->result.add(value)); return result; } //根据value查找key public synchronized k getKeyByValue(v value){ //遍历所有key组成的集合 for (k key:map.keySet()){ //如果指定key对应的value与被搜索的value相同,则返回对应的key if(map.get(key)==value||map.get(key).equals(value)){ return key; } } return null; } //实现put()方法,该方法不允许value重复 public synchronized v put(k key,v value){ //遍历所有value组成的集合 for (v val:valueSet()){ //如果某个value与试图放入集合的value相同 //则抛出一个RuntimeException异常 if (val.equals(value)&&val.hashCode()==value.hashCode()){ throw new RuntimeException("MyMap实例不允许有重复的value"); } } return map.put(key,value); }}
CrazyitProtocol类
package Test;public interface CrazyitProtocol { //定义协议字符串的长度 int PROTOCOL_LEN=2; //下面是一些协议字符串,服务器端和客户端交换的信息都应该在前后添加这种特殊字符串 String MSG_ROUND="ηθ"; String USER_ROUND="∏∑"; String LOGIN_SUCCESS="1"; String NAME_REP="-1"; String PRIVATE_ROUND="★【"; String SPLIT_SIGN="卐";}
运行结果:
打开服务器并且运行三个客户端用户名分别是xuwei,jiji和yaou
首先发送一句公开信息:
xuwei发送了一句话
jiji收到:
yaou收到:
再发送一句私聊信息给jiji
xuwei发送了一句悄悄话:
jiji收到:
yaou没有收到:
关于"Java怎么用局域网实现聊天室功能"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"Java怎么用局域网实现聊天室功能"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。
输入
用户
服务器
服务
输出
信息
用户名
客户
字符
网络
字符串
客户端
线程
功能
局域
局域网
聊天室
不断
方法
登录
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网站挂到服务器上
歌唱祖国五线谱软件开发
濮阳市高亚网络技术有限公司
传统网络安全产品
dvr管理服务器作用
阿里云搭建mc服务器
服务器负载状态100%会出问题
佛山dns服务器地址
网络安全策略都有哪些
服务器有没有做防护能看到么
会话管理和业务管理服务器
网络安全公益宣传视频
活动目录ad服务器
湖南联想服务器维修调试虚拟主机
中兴网络安全实验室深圳
花小猪软件开发地是哪里
视频安防管理平台服务器
django 服务器部署
云服务器 百度百科
兴化市安迪网络技术工作室
sq 数据库怎么下载
佛山dns服务器地址
网络安全 幼儿 宣传
医院网络安全宣传图片
筛选其他表格数据库
数据库字段定义较长
视频安防管理平台服务器
兴化市安迪网络技术工作室
全球业务数据库同步
数据库常用的控制技术有哪些