这篇文章主要为大家详细介绍了Java实现简单的聊天室功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了Java实现简单聊天室功能的具体代码,供大家参考,具体内容如下
一、客户端的创建
1.我们可以用Socket来创建客户端
/**
*@类名 Client
*@描述 TODO 客户端 1
*@版本 1.0
*@创建人 XuKang
*@创建时间 2020/9/24 16:18
**/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("-----Client1-----");
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String name =br.readLine();
//1、建立连接: 使用Socket创建客户端 +服务的地址和端口
Socket client =new Socket("localhost",8888);
//2、客户端发送消息
new Thread(new Send(client,name)).start();
new Thread(new Receive(client)).start();
}
}
2.这时我们需要接受其他客户端发送的数据,我们需要创建一个客户端的接收方法和发送方法,我可以用阻塞式的方式进行接收和发送,考虑到多线程的安全性,可以实现Runnable
1.Send发送端:
/**
*@类名 Send
*@描述 TODO 使用多线程封装:发送端
*@版本 1.0
*@创建人 XuKang
*@创建时间 2020/9/24 16:23
**/
public class Send implements Runnable {
private BufferedReader console ;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name;
public Send(Socket client,String name) {
this.client =client;
console =new BufferedReader(new InputStreamReader(System.in));
this.isRunning = true;
this.name = name;
try {
dos =new DataOutputStream(client.getOutputStream());
//发送名称
send(name);
} catch (IOException e) {
System.out.println("==1==");
this.release();
}
}
@Override
public void run() {
while(isRunning) {
String msg = getStrFromConsole();
if(!msg.equals("")) {
send(msg);
}
}
}
//发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println(e);
System.out.println("===3==");
release();
}
}
/**
* 从控制台获取消息
* @return
*/
private String getStrFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
//释放资源
private void release() {
this.isRunning = false;
CloseUtils.close(dos,client);
}
}
2.接收端
/**
*@类名 Receive
*@描述 TODO 使用多线程封装:接收端
*@版本 1.0
*@创建人 XuKang
*@创建时间 2020/9/24 16:22
**/
public class Receive implements Runnable {
private DataInputStream dis ;
private Socket client;
private boolean isRunning;
public Receive(Socket client) {
this.client = client;
this.isRunning = true;
try {
dis =new DataInputStream(client.getInputStream());
} catch (IOException e) {
System.out.println("====离开一位=====");
release();
}
}
//接收消息
private String receive() {
String msg ="";
try {
msg =dis.readUTF();
} catch (IOException e) {
System.out.println("====接收消息异常====");
release();
}
return msg;
}
@Override
public void run() {
while(isRunning) {
String msg =receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}
}
//释放资源
private void release() {
this.isRunning = false;
CloseUtils.close(dis,client);
}
}
3.统一释放资源的方法可以提出,服务的也用得上
/**
*@类名 CloseUtils
*@描述 TODO 工具类,统一释放资源
*@版本 1.0
*@创建人 XuKang
*@创建时间 2020/9/24 16:20
**/
public class CloseUtils {
/**
* 释放资源
*/
public static void close(Closeable... targets ) {
for(Closeable target:targets) {
try {
if(null!=target) {
target.close();
}
}catch(Exception e) {
}
}
}
}
二、客户端的创建
服务端用ServerSocket创建,如果我们吧服务的和客户端看成事一个通信通道(Channel),那么每个客户端的接入都会创建一个通信通道,那么通信通道的创建也需要实现多线程,可以实现Runnable接口,我们存放通道可以用线程容器CopyOnWriteArrayList来存放通道。
/**
*@类名 Chat
*@描述 TODO Socket服务端(测试类)
*@版本 1.0
*@创建人 XuKang
*@创建时间 2020/9/24 16:17
**/
public class Chat {
private static CopyOnWriteArrayList<Channel> all =new CopyOnWriteArrayList<Channel>();
public static void main(String[] args) throws IOException {
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket创建服务器
ServerSocket server =new ServerSocket(8888);
// 2、阻塞式等待连接 accept
while(true) {
Socket client =server.accept();
System.out.println("一个客户端建立了连接");
Channel c =new Channel(client);
all.add(c); //管理所有的成员
new Thread(c).start();
}
}
//一个客户代表一个Channel
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
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;
//获取名称
this.name =receive();//退出出聊天室
//欢迎你的到来
this.send("欢迎你的到来");
sendOthers(this.name+"来了徐康聊天室",true);//暂时固定为私聊
} catch (IOException e) {
System.out.println("---1------");
release();
}
}
//接收消息
private String receive() {
String msg ="";
try {
msg =dis.readUTF();
} catch (IOException e) {
System.out.println("---2------");
release();
}
return msg;
}
//发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("---3------");
release();
}
}
/**
* @方法名 sendOthers
* @描述 TODO 群聊:获取自己的消息,发给其他人,需要设置isSys为false
* TODO 私聊: 约定数据格式: @xxx:msg
* @参数 msg 发送内容
* @返回值
* @创建人 XuKang
* @创建时间 2020/9/24 16:28
*/
private void sendOthers(String msg,boolean isSys) {
boolean isPrivate = msg.startsWith("@");
if(isPrivate) { //私聊
int idx =msg.indexOf(":");
//获取目标和数据
String targetName = msg.substring(1,idx);
msg = msg.substring(idx+1);
for(Channel other: all) {
if(other.name.equals(targetName)) {//目标
other.send(this.name +"悄悄地对您说:"+msg);
break;
}
}
}else {
for(Channel other: all) {
if(other==this) { //自己
continue;
}
if(!isSys) {
other.send(this.name +"对所有人说:"+msg);//群聊消息
}else {
other.send(msg); //系统消息
}
}
}
}
//释放资源
private void release() {
this.isRunning = false;
CloseUtils.close(dis,dos,client);
//退出
all.remove(this);
sendOthers(this.name+"离开大家庭...",true);
}
@Override
public void run() {
while(isRunning) {
String msg = receive() ;
if(!msg.equals("")) {
//send(msg);
sendOthers(msg,false);
}
}
}
}
}
三、效果如下
1.启动服务端
2.启动客户端
3.发送消息
总结
此案例只能用来打发时间,入门网络编程可以参考一下,真正的开发不会这么弄。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程学习网。
沃梦达教程
本文标题为:Java实现简单的聊天室功能
基础教程推荐
猜你喜欢
- java基础知识之FileInputStream流的使用 2023-08-11
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- Java数据结构之对象比较详解 2023-03-07
- springboot自定义starter方法及注解实例 2023-03-31
- java实现多人聊天系统 2023-05-19
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- Java实现查找文件和替换文件内容 2023-04-06
- Java实现线程插队的示例代码 2022-09-03
- Java文件管理操作的知识点整理 2023-05-19
- Java并发编程进阶之线程控制篇 2023-03-07