服务端
package study_05;
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;
/*
* 目标: 支持群聊
*/
public class MultiThreadCheatServerV3 {
private static CopyOnWriteArrayListall = new CopyOnWriteArrayList<>();//CopyOnWriteArrayList支持边遍历边写入
public static void main(String[] args) throws IOException {
System.out.println("------Server--------");
ServerSocket server = new ServerSocket(9999);//开启服务器
while (true) {//循环接收客户端
Socket client = server.accept();//阻塞接收
System.out.println("有客户端连接上");
Channel c = new Channel(client);
all.add(c);//管理所有的成员
new Thread(c).start();
}
}
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRunning = true;
private String name;
public Channel(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
this.name = recieve();
} catch (IOException e) {
release();//报错则释放资源
}
}
//接受消息
private String recieve() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
return msg;
};
//发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
release();
}
}
//群聊发送消息
private void sendOther(String msg) {
boolean isPrivate = msg.startsWith("@");
if (isPrivate) {
int index = msg.indexOf(":");
String targetName = msg.substring(1, index);
msg = msg.substring(index+1);
for (Channel other : all) {
if (other.name.equals(targetName)) {
other.send(this.name + "悄悄对你说:" + msg);
}
}
}else {
for (Channel other : all) {
if (other == this) {
continue;
}
other.send(this.name + ":发送所有人--->" + msg);
}
}
};
//释放资源
private void release() {
System.out.println("服务器出错");
isRunning = false;
all.remove(this);//
IOutils.close(dis,dos,client);
}
@Override
public void run() {
while (isRunning) {
String msg = recieve();
if (!msg.equals("")) {
sendOther(msg);
}
}
}
}
}
客户端
package study_05;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class MultiThreadCheatClientV3 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("------Client--------");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入名字:");//输入用户名
String name = reader.readLine();
Socket client = new Socket("localhost",9999);
new Thread(new Send(client,name)).start();//开启发送消息线程
new Thread(new Recieve(client)).start();//开启接收消息线程
}
}
发送消息类
package study_05;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/*
*
* 发送消息类
*
*/
public class Send implements Runnable{
private DataOutputStream dos;
private Socket client;
private boolean isRunning = true;
private BufferedReader reader;
private String name;
public Send(Socket client,String name) {
this.name = name;
this.client = client;
reader = new BufferedReader(new InputStreamReader(System.in));
try {
dos = new DataOutputStream(client.getOutputStream());
send(name);
} catch (IOException e) {
release();
}
}
//从控制台接收消息
private String getMsgFromConsole() {
try {
return reader.readLine();
} catch (IOException e) {
release();
}
return "";
}
//发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
release();
}
}
@Override
public void run() {
while (isRunning) {
String msg = getMsgFromConsole();
if (!msg.equals("")) {//消息不为空
send(msg);//发送消息
}
}
}
//释放资源
private void release() {
System.out.println("客户端发送出错");
isRunning = false;
IOutils.close(dos,client);
}
}