本文实例为大家分享了Java Socket实现聊天室的具体代码,供大家参考,具体内容如下
1 创建登录判断类UserLogin
import java.util.HashSet;
import java.util.Set;
public class UserLogin {
public static boolean login(String username) {
Set<String> set = initUser();
// set中含有该username则登录成功
return set.contains(username);
}
public static Set<String> initUser() {
Set<String> set = new HashSet<>();
set.add("111");
set.add("222");
set.add("333");
set.add("444");
set.add("555");
return set;
}
}
2 创建登录服务器LoginServer
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginServer {
public static void main(String[] args) {
int port = 6666;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("登录服务器已经启动");
while (true) {
Socket socket = serverSocket.accept();
// 接收Client输出的信息(username)
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String username = bufferedReader.readLine();
// 调用登录方法,判断是否成功登录
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
if (UserLogin.login(username)) {
System.out.println(username + "登录成功");
// 登录成功输出"true"到Client
printStream.println("true");
} else {
System.out.println(username + "登录失败");
// 登录失败则输出"false"到Client
printStream.println("false");
}
printStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3 创建聊天服务器ChatServer
import com.socket.socketChatroom.bio.thread.ChatThread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class ChatServer {
// 保存当前聊天中的所有Map<username,Socket>
public static Map<String, Socket> socketMap = new HashMap<>();
public static void main(String[] args) {
int port = 9999;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("聊天服务器已经启动");
while (true) {
Socket socket = serverSocket.accept();
// 接收Client输出的username
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String username = bufferedReader.readLine();
System.out.println(username + "连接到聊天服务器");
// 连接聊天服务器成功则将它的<username,Socket>放入socketMap中
socketMap.put(username, socket);
System.out.println(socketMap);
// 因为可能有多个Client与ChatServer进行交互,所以一旦有Client连接成功就新创建一个线程与之交互
new ChatThread(username,socket).start();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
4 创建客户端Client
import com.socket.socketChatroom.bio.thread.ReadThread;
import com.socket.socketChatroom.bio.thread.WriteThread;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
// 服务端地址,端口号
String ip = "127.0.0.1";// 本机IP地址
int port = 6666; // 必须和LoginServer的端口一样
try {
Socket client = new Socket(ip, port);
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名");
String username = scanner.nextLine();
// 将用户名输出到LoginServer
OutputStream outputStream = client.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.println(username);
printStream.flush();
// 接收LoginServer输出的是否登录成功标志("true"或"false")
InputStream inputStream = client.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String state = bufferedReader.readLine();
// 如果为"true",则为登录成功,可以开始聊天
if (Boolean.parseBoolean(state)) {
chat(username);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void chat(String username) {
try {
String ip = "127.0.0.1";// 本机IP地址
int port = 9999;// 必须和ChatServer的端口一样
// 连接聊天服务器ChatServer
Socket socket = new Socket(ip, port);
// 将username输出到ChatServer
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.println(username);
printStream.flush();
// 因为聊天的收发消息不一定是与同一个人,所以创建两个线程分别用于收和发
new ReadThread(socket).start();
new WriteThread(socket).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
5 创建服务器用于处理聊天的线程类ChatThread
import com.socket.socketChatroom.bio.server.ChatServer;
import java.io.*;
import java.net.Socket;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class ChatThread extends Thread {
private final String username;
private final Socket socket;
public ChatThread(String username, Socket socket) {
this.username = username;
this.socket = socket;
}
@Override
public void run() {
while (true) {
try {
// 接收Client的WriteThread线程输出的消息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String message = bufferedReader.readLine();
System.out.println(username + "说: " + message);
// 将当前所有在线的Client的username存入usernameSet中
Map<String, Socket> socketMap = ChatServer.socketMap;
Set<String> usernameSet = new HashSet<>();
for (Map.Entry<String, Socket> map : socketMap.entrySet()) {
usernameSet.add(map.getKey());
}
// 以"-"作为标识符,判断是群聊还是单聊
String[] values = message.split("-");
if (values.length == 2 && usernameSet.contains(values[0])) { //单聊
// values[0]为要指定发送的Client的username
OutputStream outputStream = socketMap.get(values[0]).getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
// values[1]为消息内容
printStream.println(username + "说: " + values[1]);
printStream.flush();
} else {//群聊
// 将消息发送到除自己之外的所有Client
for (String username : usernameSet) {
if (socket != socketMap.get(username)) {
OutputStream outputStream = socketMap.get(username).getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.println(this.username + "说: " + message);
printStream.flush();
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
6 创建客户端Client用于发送消息的线程类WriteThread
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class WriteThread extends Thread {
private final Socket socket;
public WriteThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true) {
try {
// 获取输出流
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
// 键盘输入要发送的消息,若为单聊,则以要发送的Client的username+"-",开头,比如"111-hello",表示向111这个Client发送"hello"
Scanner scanner = new Scanner(System.in);
System.out.println("请输入聊天内容: ");
String message = scanner.nextLine();
// 输出消息到ChatServer
printStream.println(message);
printStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
7 创建客户端Client用于接收消息的线程类ReadThread
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class ReadThread extends Thread {
private final Socket socket;
public ReadThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true) {
try {
// 从ChatServer获取消息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String message = bufferedReader.readLine();
System.out.println(message);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
项目结构如下图
8 测试
先运行LoginServer和ChatServer,再运行多个Client
设置IDEA允许运行多个实例
8.1 登录
8.2 群聊
8.3 单聊