Java 聊天系统实现
下面是一个基于Java Socket编程的简单聊天系统实现,包含服务器端和客户端代码。
1. 服务器端代码 (ChatServer.java)
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer {
private static final int PORT = 12345;
private static Set<ClientHandler> clientHandlers = new HashSet<>();
public static void main(String[] args) {
System.out.println("聊天服务器启动中...");
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("服务器已启动,等待客户端连接...");
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("新客户端连接: " + clientSocket);
ClientHandler clientHandler = new ClientHandler(clientSocket);
clientHandlers.add(clientHandler);
clientHandler.start();
}
} catch (IOException e) {
System.err.println("服务器异常: " + e.getMessage());
}
}
// 广播消息给所有客户端
public static void broadcast(String message, ClientHandler excludeClient) {
for (ClientHandler client : clientHandlers) {
if (client != excludeClient) {
client.sendMessage(message);
}
}
}
// 移除客户端
public static void removeClient(ClientHandler client) {
clientHandlers.remove(client);
System.out.println("客户端断开连接: " + client.getClientSocket());
}
// 客户端处理线程
private static class ClientHandler extends Thread {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
private String username;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
public Socket getClientSocket() {
return clientSocket;
}
@Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// 获取用户名
out.println("请输入你的用户名:");
username = in.readLine();
System.out.println(username + " 加入了聊天室");
broadcast(username + " 加入了聊天室", this);
String clientMessage;
while ((clientMessage = in.readLine()) != null) {
if (clientMessage.equalsIgnoreCase("exit")) {
break;
}
System.out.println(username + ": " + clientMessage);
broadcast(username + ": " + clientMessage, this);
}
} catch (IOException e) {
System.err.println("客户端处理异常: " + e.getMessage());
} finally {
try {
if (clientSocket != null) {
clientSocket.close();
}
} catch (IOException e) {
System.err.println("关闭客户端连接异常: " + e.getMessage());
}
removeClient(this);
broadcast(username + " 离开了聊天室", null);
System.out.println(username + " 离开了聊天室");
}
}
public void sendMessage(String message) {
out.println(message);
}
}
}2. 客户端代码 (ChatClient.java)
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ChatClient {
private static final String SERVER_ADDRESS = "localhost";
private static final int SERVER_PORT = 12345;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try (Socket socket = new Socket(SERVER_ADDRESS, SERVER_PORT)) {
System.out.println("已连接到聊天服务器");
// 启动消息接收线程
new Thread(new MessageReceiver(socket)).start();
// 处理用户输入
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 读取服务器欢迎消息
String serverMessage;
while ((serverMessage = in.readLine()) != null) {
System.out.println(serverMessage);
if (serverMessage.startsWith("请输入你的用户名:")) {
String username = scanner.nextLine();
out.println(username);
} else {
String userInput = scanner.nextLine();
if (userInput.equalsIgnoreCase("exit")) {
out.println("exit");
break;
}
out.println(userInput);
}
}
} catch (UnknownHostException e) {
System.err.println("无法找到服务器: " + e.getMessage());
} catch (IOException e) {
System.err.println("I/O异常: " + e.getMessage());
} finally {
scanner.close();
System.out.println("已断开与服务器的连接");
}
}
// 消息接收线程
private static class MessageReceiver implements Runnable {
private Socket socket;
public MessageReceiver(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String serverMessage;
while ((serverMessage = in.readLine()) != null) {
System.out.println(serverMessage);
}
} catch (IOException e) {
System.err.println("接收消息异常: " + e.getMessage());
}
}
}
}3. 系统功能说明
服务器端功能
监听指定端口(12345)等待客户端连接
为每个客户端创建独立的处理线程
接收客户端消息并广播给所有其他客户端
处理客户端连接和断开事件
支持用户名设置
客户端功能
连接到指定服务器
设置用户名
发送消息到服务器
接收并显示其他用户的消息
支持退出命令("exit")
4. 如何运行
首先编译并运行服务器端:
javac ChatServer.java java ChatServer
然后可以运行多个客户端(需要打开多个终端):
javac ChatClient.java java ChatClient
在客户端中输入用户名后即可开始聊天
5. 扩展建议
图形界面:使用Java Swing或JavaFX为客户端添加图形界面
私聊功能:实现用户之间的私密聊天
用户列表:服务器维护在线用户列表并通知所有客户端
消息历史:保存聊天记录
加密通信:使用SSL/TLS加密通信内容
数据库支持:使用数据库存储用户信息和聊天记录
多房间支持:实现多个聊天室功能
6. 简单图形界面客户端示例 (可选)
如果你想为客户端添加简单的图形界面,可以使用以下代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class GUIChatClient {
private JFrame frame;
private JTextArea chatArea;
private JTextField inputField;
private PrintWriter out;
private String username;
public GUIChatClient() {
initializeGUI();
connectToServer();
}
private void initializeGUI() {
frame = new JFrame("聊天客户端");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 400);
chatArea = new JTextArea();
chatArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(chatArea);
inputField = new JTextField();
inputField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sendMessage();
}
});
JButton sendButton = new JButton("发送");
sendButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sendMessage();
}
});
JPanel bottomPanel = new JPanel(new BorderLayout());
bottomPanel.add(inputField, BorderLayout.CENTER);
bottomPanel.add(sendButton, BorderLayout.EAST);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(bottomPanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
private void connectToServer() {
try {
Socket socket = new Socket("localhost", 12345);
out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 获取用户名
username = JOptionPane.showInputDialog(frame, "请输入你的用户名:");
out.println(username);
// 启动消息接收线程
new Thread(new MessageReceiver(in)).start();
} catch (IOException e) {
JOptionPane.showMessageDialog(frame, "连接服务器失败: " + e.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
private void sendMessage() {
String message = inputField.getText();
if (!message.isEmpty()) {
out.println(message);
inputField.setText("");
}
}
private class MessageReceiver implements Runnable {
private BufferedReader in;
public MessageReceiver(BufferedReader in) {
this.in = in;
}
@Override
public void run() {
try {
String message;
while ((message = in.readLine()) != null) {
final String msg = message;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
chatArea.append(msg + "
");
}
});
}
} catch (IOException e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
chatArea.append("与服务器的连接已断开
");
}
});
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GUIChatClient();
}
});
}
}这个简单的聊天系统展示了Java网络编程的基本概念,你可以根据需要进一步扩展和完善功能。
- 上一篇:没有了
- 下一篇:如何保护聊天系统的通信安全?
- 文章导航