基于Java实现简易的局域网对话系统攻略
介绍
在本文中,我们将基于Java语言开发一款简易的局域网对话系统,方便局域网内的用户之间进行在线聊天。系统将通过Java Socket和Swing进行 GUI 界面设计,并利用Java多线程技术实现并发通信。
准备工作
在开发项目之前,需要准备以下环境:
- JDK环境: 可以通过官网下载相关版本并安装。
- Eclipse IDE: 后续开发实现以Eclipse为例。
- 相关包、jar文件: 项目中需要用到的jar包可在 Maven 仓库中进行下载。
项目结构
在开始实现之前,需要创建相应的项目目录结构来组织后续开发所需的文件。具体如下:
.
├── bin
├── lib
│ ├── commons-io-2.8.0.jar
│ ├── commons-lang3-3.12.0.jar
│ └── log4j-api-2.14.1.jar
└── log4j-core-2.14.1.jar
└── src
├── client
│ ├── Client.java
│ └── ClientGUI.java
├── common
│ └── Message.java
├── server
│ ├── Server.java
│ └── ServerGUI.java
└── util
├── Connection.java
├── MessageListener.java
└── MessageSender.java
- lib: 存放项目所需的所有第三方jar包。
- src: 存放所有源码文件。具体分为客户端代码和服务端代码。
服务端实现
设计协议
在开始实现之前,需要先约定客户端和服务端通信所需的协议格式。这里我们采用二进制协议,具体内容如下:
- 第1-4字节: 表示消息长度(int类型)
- 第5-6字节: 表示消息类型(short类型)
- 第7-字节: 表示消息内容(byte数组类型)
编写服务端代码
- 创建
Server
类,用于监听客户端连接并分发消息。
示例代码:
public class Server {
private ServerSocket serverSocket;
private final List<Connection> connections;
public Server(int port) {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
}
connections = new ArrayList<>();
}
public void start() {
while (true) {
try {
Socket clientSocket = serverSocket.accept();
Connection connection = new Connection(clientSocket);
connections.add(connection);
MessageListener listener = new MessageListener(connection, connections);
listener.start();
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
}
}
}
public static void main(String[] args) {
new Server(9999).start();
}
}
- 创建
ServerGUI
类,用于监听服务端的启动和关闭。
示例代码:
public class ServerGUI {
private JFrame frame;
private JTextArea textArea;
public ServerGUI() {
frame = new JFrame("Server");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 添加日志记录器
textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
frame.add(scrollPane);
frame.setVisible(true);
// 启动服务端
new Thread(() -> {
Server server = new Server(9999);
server.start();
}).start();
}
public void log(String message) {
textArea.append(message + "\n");
}
public static void main(String[] args) {
new ServerGUI();
}
}
- 创建
Connection
类,用于处理客户端连接并向客户端发送消息。每一个Connection
实例对应一个客户端连接。
示例代码:
public class Connection {
private final Socket socket;
private final OutputStream outputStream;
public Connection(Socket socket) throws IOException {
this.socket = socket;
this.outputStream = socket.getOutputStream();
}
public void send(Message message) throws IOException {
outputStream.write(message.toBytes());
outputStream.flush();
}
public void close() throws IOException {
socket.close(); // 关闭连接
// 通知服务端移除连接
}
}
- 创建
MessageListener
类,用于监听客户端发来的消息并广播给所有客户端。
示例代码:
public class MessageListener extends Thread {
private final Connection connection;
private final List<Connection> connections;
public MessageListener(Connection connection, List<Connection> connections) {
this.connection = connection;
this.connections = connections;
}
@Override
public void run() {
while (true) {
try {
DataInputStream in = new DataInputStream(connection.socket.getInputStream());
int length = in.readInt();
short type = in.readShort();
byte[] content = new byte[length - 6];
in.read(content);
Message message = new Message(type, content);
for (Connection conn : connections) {
if (conn != connection) {
conn.send(message);
}
}
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
break;
}
}
try {
connection.close();
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
}
}
}
客户端实现
设计GUI界面
客户端需要具有如下GUI界面:
- 连接服务器:
- 输入服务器IP地址和端口号以建立连接。
- 点击“Connect”按钮建立连接。
- 在线聊天:
- 显示聊天信息。
- 可以输入发送消息。
编写客户端代码
- 创建
Message
类,用于封装消息类型和内容。
示例代码:
public class Message {
private short type;
private byte[] content;
public Message(short type, byte[] content) {
this.type = type;
this.content = content;
}
public byte[] toBytes() {
ByteBuffer buffer = ByteBuffer.allocate(6 + content.length);
buffer.putInt(6 + content.length);
buffer.putShort(type);
buffer.put(content);
return buffer.array();
}
}
- 创建
Client
类,用于建立和服务器的连接,并向服务器发送消息。
示例代码:
public class Client {
private Socket socket;
private InputStream in;
private OutputStream out;
public Client(String serverAddress, int serverPort) throws IOException {
socket = new Socket(serverAddress, serverPort);
in = socket.getInputStream();
out = socket.getOutputStream();
}
public void send(Message message) throws IOException {
out.write(message.toBytes());
out.flush();
}
public void close() throws IOException {
socket.close();
}
}
- 创建
ClientGUI
类,用于实现GUI界面和用户交互。
示例代码:
public class ClientGUI implements ActionListener {
private Client client;
private JFrame frame;
private JTextField textField;
private JTextArea textArea;
private JButton sendButton;
public ClientGUI() {
frame = new JFrame("Client");
frame.setLayout(new BorderLayout());
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 连接服务器
JPanel connectPanel = new JPanel();
connectPanel.setLayout(new FlowLayout());
JLabel addressLabel = new JLabel("Server Address:");
JTextField addressField = new JTextField("localhost");
addressField.setColumns(10);
JLabel portLabel = new JLabel("Server Port:");
JTextField portField = new JTextField("9999");
portField.setColumns(5);
JButton connectButton = new JButton("Connect");
connectButton.addActionListener(e -> {
try {
client = new Client(addressField.getText(), Integer.parseInt(portField.getText()));
MessageListener listener = new MessageListener(client, this);
listener.start();
} catch (IOException ex) {
ex.printStackTrace();
}
});
connectPanel.add(addressLabel);
connectPanel.add(addressField);
connectPanel.add(portLabel);
connectPanel.add(portField);
connectPanel.add(connectButton);
frame.add(connectPanel, BorderLayout.NORTH);
// 在线聊天
textArea = new JTextArea();
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
frame.add(scrollPane, BorderLayout.CENTER);
textField = new JTextField();
sendButton = new JButton("Send");
sendButton.addActionListener(this);
JPanel messagePanel = new JPanel();
messagePanel.setLayout(new BorderLayout());
messagePanel.add(textField, BorderLayout.CENTER);
messagePanel.add(sendButton, BorderLayout.EAST);
frame.add(messagePanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
try {
String content = textField.getText();
if (!content.isEmpty()) {
Message message = new Message((short) 0, content.getBytes(StandardCharsets.UTF_8));
client.send(message);
}
textField.setText("");
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void log(String message) {
textArea.append(message + "\n");
}
public static void main(String[] args) {
new ClientGUI();
}
}
- 创建
MessageListener
类,用于监听服务端发来的消息并打印出来。
示例代码:
public class MessageListener extends Thread {
private final Client client;
private final ClientGUI clientGUI;
public MessageListener(Client client, ClientGUI clientGUI) {
this.client = client;
this.clientGUI = clientGUI;
}
@Override
public void run() {
while (true) {
try {
DataInputStream in = new DataInputStream(client.in);
int length = in.readInt();
short type = in.readShort();
byte[] content = new byte[length - 6];
in.read(content);
Message message = new Message(type, content);
clientGUI.log(new String(message.getContent(), StandardCharsets.UTF_8));
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
break;
}
}
try {
client.close();
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
}
}
}
测试
在本地启动服务端,然后启动多个客户端,输入相同的IP地址和端口号建立连接,即可进行测试。
结论
本文详细讲解了如何基于Java实现简易的局域网对话系统,在代码实现过程中涉及到了Java Socket、Swing、多线程等技术,涵盖了Java开发常用的技术点。本文提供了完整的代码示例以及目录结构、协议设计的详细说明,可供读者逐步学习和实践。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于Java实现简易的局域网对话系统 - Python技术站