
技术栈与准备
开发多用户在线聊天室需要结合Java Socket编程和MySQL数据库。Java负责网络通信,MySQL用于存储用户信息和聊天记录。确保已安装JDK、MySQL及对应JDBC驱动。
数据库设计
创建数据库chatroom,设计两张核心表:
- users表:存储用户信息
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(50) NOT NULL, online_status BOOLEAN DEFAULT false ); - messages表:存储聊天记录
CREATE TABLE messages ( id INT AUTO_INCREMENT PRIMARY KEY, sender_id INT NOT NULL, content TEXT NOT NULL, send_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (sender_id) REFERENCES users(id) );
服务端实现
使用Java ServerSocket处理多客户端连接,每个客户端通过独立线程处理。
public class ChatServer {
private static final int PORT = 8888;
private static Set<ClientHandler> clients = new HashSet<>();
private static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server started on port " + PORT);
while (true) {
Socket clientSocket = serverSocket.accept();
ClientHandler clientThread = new ClientHandler(clientSocket);
clients.add(clientThread);
pool.execute(clientThread);
}
}
}
客户端处理器
每个客户端连接后,独立线程处理消息收发和数据库交互。
class ClientHandler implements Runnable {
private Socket socket;
private PrintWriter out;
private BufferedReader in;
private String username;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// 用户认证逻辑
username = authenticateUser();
broadcast(username + " joined the chat");
// 消息处理循环
String inputLine;
while ((inputLine = in.readLine()) != null) {
if (inputLine.equals("/exit")) break;
saveMessageToDB(inputLine);
broadcast(username + ": " + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 清理资源
}
}
}
数据库交互
通过JDBC实现用户验证和消息存储。
private String authenticateUser() throws IOException {
out.println("Enter username:");
String username = in.readLine();
out.println("Enter password:");
String password = in.readLine();
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS)) {
String sql = "SELECT * FROM users WHERE username=? AND password=?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();
if (!rs.next()) {
out.println("Invalid credentials");
return authenticateUser(); // 递归重试
}
// 更新在线状态
sql = "UPDATE users SET online_status=true WHERE username=?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, username);
stmt.executeUpdate();
}
return username;
}
消息广播功能
向所有连接的客户端发送消息。
private void broadcast(String message) {
for (ClientHandler client : ChatServer.clients) {
if (client != this) {
client.out.println(message);
}
}
}
客户端实现
客户端通过Socket连接到服务器,并开启两个线程分别处理消息发送和接收。
public class ChatClient {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 8888);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
Scanner scanner = new Scanner(System.in)) {
// 接收服务器消息的线程
new Thread(() -> {
while (true) {
String response = in.readLine();
if (response == null) break;
System.out.println(response);
}
}).start();
// 用户输入处理
while (scanner.hasNextLine()) {
String input = scanner.nextLine();
out.println(input);
if (input.equals("/exit")) break;
}
}
}
}
功能扩展建议
- 用户注册:增加用户注册功能,将新用户插入数据库
- 历史消息:连接时加载最近的聊天记录
- 私聊功能:支持
@username格式的私聊消息 - 心跳检测:定时检测客户端连接状态,自动清理断连用户
注意事项
- 使用线程池管理客户端连接,避免资源耗尽
- 数据库操作需要处理SQL异常和连接关闭
- 消息广播时需同步处理
clients集合,避免并发修改异常 - 生产环境应使用加密通信和密码哈希存储
612

被折叠的 条评论
为什么被折叠?



