Java实现简单的聊天室功能

网友投稿 255 2022-07-25


本文实例为大家分享了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 all =new CopyOnWriteArrayList();

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;

//获取名称

http:// 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.发送消息

总结

此案例只能用来打发时间,入门网络编程可以参考一下,真正的开发不会这么弄FbcrzHT。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:深入了解Java.Util.Date详情
下一篇:Clojure 与Java对比少数据结构多函数胜过多个单独类的优点
相关文章

 发表评论

暂时没有评论,来抢沙发吧~