- 一對一單聊的實現:客戶端帶着發送方ID和接收方ID、信息發送給服務端,服務端從socket池中找出接收方ID進行轉發。
- 羣發的實現:客戶端發送羣發消息給服務端,然後服務端從socket池中取出所有正在連接的客戶端,然後進行轉發
import org.junit.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.UUID;
public class socket {
static java.util.Map<String, Socket> socketMap = new HashMap<>();
public static void main(String[] args) throws InterruptedException {
Thread server = new Thread(() -> {
try {
ServerSocket serverSocket = new ServerSocket(6666);
while (true) {
Socket socket = serverSocket.accept();
serverRead(socket);
}
} catch (IOException e) {
System.out.println("報錯了");
e.printStackTrace();
}
});
server.join();
server.start();
mySocket b = clientConServer();
mySocket a = clientConServer();
try {
clientSend(a,"你好",b.id);
Thread.sleep(1000);
clientSend(b,"你也好",a.id);
Thread.sleep(1000);
clientSendAll(a,"大家好");
} catch (IOException e) {
e.printStackTrace();
}
Thread.sleep(1000);
disconnect(a);
Thread.sleep(1000);
disconnect(b);
try {
a.socket.close();
b.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 客戶端與服務端建立連接 C
*/
public static mySocket clientConServer() {
mySocket socket = new mySocket();
try {
PrintWriter printWriter = new PrintWriter(socket.socket.getOutputStream());
printWriter.write("connect\n");
printWriter.flush();
printWriter.write(socket.id+"\n");
printWriter.flush();
readThread(socket.socket);
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
/**
* 服務器監聽 S
*/
public static void serverRead(Socket socket) throws IOException {
//開啓服務器輸入監聽線程
SocketInterface socketRead = (Socket socket1) -> {
Thread thread = new Thread() {
public Socket socket = socket1;
String info;
@Override
public void run() {
try {
//獲取輸入流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket1.getInputStream()));
while ((info = bufferedReader.readLine()) != null) {
//如果監聽到連接指令:connect,則獲取socketId,並將此socket連接保存到靜態map中
if (info.equals("connect")) {
//獲取socketId
String key = bufferedReader.readLine();
//存入在靜態Map中
socketMap.put(key, socket);
//回傳給客戶端,提示已經建立連接
PrintWriter we = new PrintWriter(socket.getOutputStream());
// System.out.println(key);
we.write("客戶端" + key + "連接服務器成功\n");
we.flush();
}
//如果監聽到連接指令:send,則獲取發送客戶端socketId:from,接受客戶端socketId:to,發送的消息:message
if ("send".equals(info)){
//發送客戶端socketId
String from = bufferedReader.readLine();
//接受客戶端socketId
String to = bufferedReader.readLine();
//發送
send(from,bufferedReader.readLine(),to);
}
//如果監聽到連接指令:sendAll,則羣發消息
if ("sendAll".equals(info)){
String from = bufferedReader.readLine();
String message = bufferedReader.readLine();
mass(message,from);
}
//如果監聽到連接指令:disconnect,則斷開與某個客戶端的連接
if ("disconnect".equals(info)){
String from = bufferedReader.readLine();
info = from;
System.out.println(from+"請求斷開連接");
socketMap.get(from).getOutputStream().close();
socketMap.get(from).getInputStream().close();
socketMap.get(from).close();
}
// System.out.println(info);
}
} catch (SocketException se) {
System.out.println(info+"已斷開");
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
};
socketRead.read(socket);
}
/**
* 客戶端接受信息 C
*
* @param socket
*/
public static void readThread(Socket socket) {
//開啓客戶端輸入監聽線程
SocketInterface socketRead = (Socket socket1) -> {
Thread thread = new Thread() {
public Socket socket = socket1;
public String info = null;
@Override
public void run() {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket1.getInputStream()));
while ((info = bufferedReader.readLine()) != null) {
System.out.println(info);
}
} catch (SocketException se) {
System.out.println("socket關閉");
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
};
socketRead.read(socket);
}
/**
* 服務器轉發羣發消息 S
*
* @param message
*/
public static void mass(String message, String fromUUID) {
//遍歷所有已連接服務器的socket
socketMap.forEach((s, socket) -> {
if (!socket.isClosed()) {
try {
// 發送信息
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.write( s+"收到來自<---"+fromUUID + "的羣發消息:" + message + "\n");
printWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
* 客戶端發送給客戶端 C
* @param a
* @param message
* @param to
* @throws IOException
*/
public static void clientSend(mySocket a,String message,String to) throws IOException {
PrintWriter printWriter = new PrintWriter(a.socket.getOutputStream());
printWriter.write("send\n");
printWriter.flush();
printWriter.write(a.id+"\n");
printWriter.flush();
printWriter.write(to+"\n");
printWriter.flush();
printWriter.write(message+"\n");
printWriter.flush();
}
/**
* 客戶端羣發消息 C
*
* @param a
* @param message
* @throws IOException
*/
public static void clientSendAll(mySocket a,String message) throws IOException {
PrintWriter printWriter = new PrintWriter(a.socket.getOutputStream());
printWriter.write("sendAll\n");
printWriter.flush();
printWriter.write(a.id+"\n");
printWriter.flush();
printWriter.write(message+"\n");
printWriter.flush();
}
/**
* 服務器轉發 S
* @param from
* @param message
* @param to
* @throws IOException
*/
public static void send(String from,String message,String to) throws IOException {
//從socket池中獲取接受客戶端socket,並寫入信息
PrintWriter printWriter = new PrintWriter(socketMap.get(to).getOutputStream());
printWriter.write(to+"\n");
printWriter.flush();
printWriter.write(from+"發送給-->"+to+":"+message+"\n");
printWriter.flush();
}
/**
*
* 斷開連接 C
*/
static void disconnect(mySocket mySocket){
try {
PrintWriter printWriter = new PrintWriter(mySocket.socket.getOutputStream());
printWriter.write("disconnect\n");
printWriter.flush();
printWriter.write(mySocket.id+"\n");
printWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class mySocket {
public String id;
public Socket socket;
mySocket() {
this.id = UUID.randomUUID().toString();
try {
this.socket = new Socket("192.168.157.1", 6666);
} catch (IOException e) {
e.printStackTrace();
}
}
}
接口類
import java.net.Socket;
public interface SocketInterface {
/**
* 開啓監聽
*/
void read(Socket socket);
}