本文目录导读:

我将为您创建一个基于Java Socket的简单聊天室案例,包含服务器端和客户端,这个案例使用控制台界面,支持多用户同时在线聊天。
项目结构
chatroom/
├── src/
│ ├── ChatServer.java # 服务器端
│ ├── ChatClient.java # 客户端
│ └── UserThread.java # 客户端线程处理
服务器端代码
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer {
private static final int PORT = 12345;
private static Set<PrintWriter> clients = new HashSet<>();
private static Map<String, PrintWriter> clientNames = new HashMap<>();
private static Map<String, String> userNames = new HashMap<>();
public static void main(String[] args) {
System.out.println("=== 聊天室服务器启动 ===");
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("服务器正在端口 " + PORT + " 监听...");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("新客户端连接: " + socket.getInetAddress());
UserThread userThread = new UserThread(socket);
Thread thread = new Thread(userThread);
thread.start();
}
} catch (IOException e) {
System.err.println("服务器错误: " + e.getMessage());
}
}
// 广播消息给所有客户端
public static synchronized void broadcast(String message, String sender) {
for (PrintWriter client : clients) {
client.println("[广播] " + sender + ": " + message);
}
}
// 发送私聊消息
public static synchronized boolean sendPrivateMessage(String toUser, String message, String sender) {
PrintWriter targetClient = clientNames.get(toUser);
if (targetClient != null) {
targetClient.println("[私聊] " + sender + ": " + message);
return true;
}
return false;
}
// 获取在线用户列表
public static synchronized String getOnlineUsers() {
if (userNames.isEmpty()) {
return "暂无在线用户";
}
StringBuilder users = new StringBuilder("在线用户: ");
for (String name : userNames.keySet()) {
users.append(name).append(" ");
}
return users.toString();
}
// 添加新客户端
public static synchronized void addClient(String username, PrintWriter writer, Socket socket) {
clients.add(writer);
clientNames.put(username, writer);
userNames.put(username, socket.getInetAddress().toString());
// 通知所有用户
broadcast(username + " 加入了聊天室", "系统");
writer.println("欢迎 " + username + " 加入聊天室!");
writer.println(getOnlineUsers());
}
// 移除客户端
public static synchronized void removeClient(String username, PrintWriter writer) {
clients.remove(writer);
clientNames.remove(username);
userNames.remove(username);
broadcast(username + " 离开了聊天室", "系统");
}
// 内部类:处理每个客户端连接
static class UserThread implements Runnable {
private Socket socket;
private PrintWriter writer;
private BufferedReader reader;
private String username;
public UserThread(Socket socket) {
this.socket = socket;
try {
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
System.err.println("创建客户端线程失败: " + e.getMessage());
}
}
@Override
public void run() {
try {
// 获取用户名
writer.println("请输入用户名: ");
username = reader.readLine();
if (username == null || username.trim().isEmpty()) {
writer.println("用户名不能为空,连接已关闭。");
socket.close();
return;
}
addClient(username, writer, socket);
writer.println("输入 /quit 退出聊天室");
writer.println("输入 /list 查看在线用户");
writer.println("输入 /msg [用户名] [消息] 发送私聊");
String input;
while ((input = reader.readLine()) != null) {
if (input.equalsIgnoreCase("/quit")) {
break;
} else if (input.equalsIgnoreCase("/list")) {
writer.println(getOnlineUsers());
} else if (input.startsWith("/msg")) {
String[] parts = input.split(" ", 3);
if (parts.length == 3) {
boolean success = sendPrivateMessage(parts[1], parts[2], username);
if (!success) {
writer.println("用户 " + parts[1] + " 不在线或不存在");
}
} else {
writer.println("私聊格式: /msg [用户名] [消息]");
}
} else {
broadcast(input, username);
}
}
removeClient(username, writer);
socket.close();
} catch (IOException e) {
System.err.println("客户端 " + username + " 连接断开");
removeClient(username, writer);
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
客户端代码
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ChatClient {
private static final String HOST = "localhost";
private static final int PORT = 12345;
private Socket socket;
private PrintWriter out;
private BufferedReader in;
private Scanner scanner;
public static void main(String[] args) {
ChatClient client = new ChatClient();
client.start();
}
public void start() {
scanner = new Scanner(System.in);
try {
socket = new Socket(HOST, PORT);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("已连接到聊天室服务器...");
// 创建线程监听服务器消息
new Thread(new MessageListener()).start();
// 用户输入循环
handleUserInput();
} catch (IOException e) {
System.err.println("连接服务器失败: " + e.getMessage());
System.exit(1);
} finally {
try {
if (socket != null) socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void handleUserInput() throws IOException {
String input;
while (true) {
input = scanner.nextLine();
out.println(input);
if (input.equalsIgnoreCase("/quit")) {
System.out.println("正在退出聊天室...");
break;
}
}
}
// 内部类:监听服务器消息
class MessageListener implements Runnable {
@Override
public void run() {
String message;
try {
while ((message = in.readLine()) != null) {
System.out.println(message);
}
} catch (IOException e) {
System.err.println("连接已断开");
}
}
}
}
运行方法
编译代码
cd chatroom/src javac ChatServer.java javac ChatClient.java
启动服务器
java ChatServer
启动多个客户端
每个客户端都需要新开一个终端:
java ChatClient
功能说明
| 命令 | 功能 |
|---|---|
/quit |
退出聊天室 |
/list |
查看在线用户 |
/msg [用户名] [消息] |
发送私聊消息 |
| 普通文字 | 广播给所有人 |
运行示例
服务器端:
=== 聊天室服务器启动 ===
服务器正在端口 12345 监听...
新客户端连接: /127.0.0.1
新客户端连接: /127.0.0.1
客户端1(用户:Alice):
请输入用户名: Alice
欢迎 Alice 加入聊天室!
在线用户: Alice
输入 /quit 退出聊天室
输入 /list 查看在线用户
输入 /msg [用户名] [消息] 发送私聊
[广播] 系统: Bob 加入了聊天室
[广播] Bob: 大家好!
[私聊] Bob: Alice,你好!
客户端2(用户:Bob):
请输入用户名: Bob
欢迎 Bob 加入聊天室!
在线用户: Alice Bob
输入 /quit 退出聊天室
输入 /list 查看在线用户
输入 /msg [用户名] [消息] 发送私聊
[广播] 系统: Bob 加入了聊天室
[广播] Bob: 大家好!
[私聊] Bob: Alice,你好!
扩展建议
- 图形界面:使用 Swing 或 JavaFX 实现 GUI 界面
- 表情/文件传输:添加表情符号、图片或文件传输功能
- 消息日志:将聊天记录保存到文件
- 用户认证:添加登录和密码验证
- 房间管理:支持创建多个聊天房间
- 消息加密:添加 SSL/TLS 加密
这个案例展示了 Java Socket 编程的核心概念,包括多线程、网络通信、同步等,可以作为学习网络编程的基础。