Java网络编程案例---聊天室

时间:2023-03-10 01:16:38
Java网络编程案例---聊天室

  网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。

  java.net包中JavaSE的API包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。

  java.net包中提供了两种常见的网络协议的支持:

  TCP:TCP是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称TCP/IP。

  UDP:UDP是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据报。

  本案例以TCP协议为例,结合多线程,实现一个多人同时聊天的聊天室。

  释放资源:

  Utils.java

 package com.bjwyj.chat;

 import java.io.Closeable;

 public class Utils {
/**
* 释放资源
*/
public static void close(Closeable... targets) {
for(Closeable target:targets) {
try {
if(target!=null) {
target.close();
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}

  服务器端:

  Chat.java

 package com.bjwyj.chat;

 import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList; /**
* 在线聊天室:服务端
* 目标:加入容器实现群聊和私聊
*
* @author 吴永吉
*
*/
public class Chat {
private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<>();
public static void main(String[] args) throws IOException {
System.out.println("------server------");
//1.指定端口:使用ServerSocket创建服务器
ServerSocket server = new ServerSocket(9999);
//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) {
isRunning = true;
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
//获取名称
this.name = receive();
//欢迎你的到来
this.send("欢迎上线");
this.sendOthers(this.name+"上线啦!",true);
}catch(Exception e) {
release();
}
} //接收消息
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("-------Chat receive------");
release();
}
return msg;
}
//发送消息
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("--------Chat send-------");
release();
}
}
/**
* 群聊:获取自己的消息,发给其他人
* 私聊:约定数据格式:@xxx:msg
* @param msg
*/
public 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(this==other) { //自己
continue;
}
if(!isSys) {
other.send(this.name+"对所有人说:"+msg); //群聊消息
}else {
other.send(msg); //系统消息
}
}
}
}
//关闭资源
public void release() {
this.isRunning = false;
Utils.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);
}
}
}
}
}

  客户端:

  Send.java

 package com.bjwyj.chat;

 import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket; /**
* 使用多线程封装了客户发送端:
* 1.发送消息
* 2.从控制台获取消息
* 3.释放资源
* 4.重写run
* @author 吴永吉
*
*/
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) {
isRunning = true;
this.client = client;
this.name = name;
console = new BufferedReader(new InputStreamReader(System.in));
try {
dos = new DataOutputStream(client.getOutputStream());
//发送名称
send(name);
} catch (IOException e) {
System.out.println("------Client Send------");
this.release();
}
} @Override
public void run() {
while(isRunning) {
String msg = this.getStringFromConsole();
if(!msg.equals("")) {
this.send(msg);
}
}
} /**
* 发送消息
*/
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("------Client send------");
release();
}
} /**
* 从控制台获取消息
*/
private String getStringFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
System.out.println("------Client console------");
release();
}
return "";
} //释放资源
private void release() {
this.isRunning = false;
Utils.close(dos,client);
}
}

  Receive.java

 package com.bjwyj.chat;

 import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket; /**
* 使用多线程封装了客户接收端
* 1.接收消息
* 2.释放资源
* 3.重写run
* @author 吴永吉
*
*/
public class Receive implements Runnable{
private DataInputStream dis;
private Socket client;
private boolean isRunning; public Receive(Socket client) {
this.isRunning = true;
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
System.out.println("------Client Receive------");
this.release();
}
} //接收消息
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("-------Receive receive------");
release();
}
return msg;
} @Override
public void run() {
while(isRunning) {
String msg = this.receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}
} //释放资源
private void release() {
this.isRunning = false;
Utils.close(dis,client);
}
}

  Client.java

 package com.bjwyj.chat;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException; /**
* 在线聊天室:客户端
*
* @author 吴永吉
*
*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("------client------");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入名称:");
String name = br.readLine();
//建立连接:使用Socket创建客户端+服务器的地址和端口号
Socket client = new Socket("localhost",9999);
//客户端发送消息
new Thread(new Send(client,name)).start();
//获取消息
new Thread(new Receive(client)).start();
}
}

  运行结果:

Java网络编程案例---聊天室Java网络编程案例---聊天室

Java网络编程案例---聊天室Java网络编程案例---聊天室