基于Java实现简易的局域网对话系统

基于Java实现简易的局域网对话系统攻略

介绍

在本文中,我们将基于Java语言开发一款简易的局域网对话系统,方便局域网内的用户之间进行在线聊天。系统将通过Java Socket和Swing进行 GUI 界面设计,并利用Java多线程技术实现并发通信。

准备工作

在开发项目之前,需要准备以下环境:

  1. JDK环境: 可以通过官网下载相关版本并安装。
  2. Eclipse IDE: 后续开发实现以Eclipse为例。
  3. 相关包、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数组类型)

编写服务端代码

  1. 创建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();
    }
}
  1. 创建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();
    }
}
  1. 创建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();     // 关闭连接
        // 通知服务端移除连接
    }
}
  1. 创建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”按钮建立连接。
  • 在线聊天:
  • 显示聊天信息。
  • 可以输入发送消息。

编写客户端代码

  1. 创建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();
    }
}
  1. 创建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();
    }
}
  1. 创建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();
    }
}
  1. 创建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技术站

(0)
上一篇 2023年5月30日
下一篇 2023年5月30日

相关文章

  • H5混合开发手机Web App入门:概念篇

    下面是《H5混合开发手机Web App入门:概念篇》的完整攻略。 概念篇 什么是H5混合开发? H5混合开发是指在原生应用中使用Web技术开发页面和功能,然后通过桥接技术将Web和原生进行互通,实现用户交互和数据传输。这样做的好处是可以借助Web的开发成果和优势,同时享受原生应用的体验和功能。 H5混合开发的优势 更快的开发速度 良好的跨平台适配性 更便捷的…

    Java 2023年5月23日
    00
  • 一文带你学会Spring JDBC的使用

    一文带你学会Spring JDBC的使用 简介 在这篇文章中,我们将会介绍Spring JDBC,以及如何使用它来连接和操作数据库。Spring JDBC是Spring框架中的一个模块,它提供了一些工具和类,使得操作数据库更加方便。 步骤 1. 添加依赖 首先,我们需要在项目中添加Spring JDBC的依赖。在Maven项目中,可以在pom.xml中添加以…

    Java 2023年6月3日
    00
  • JAVA基于SnakeYAML实现解析与序列化YAML

    下面就是“JAVA基于SnakeYAML实现解析与序列化YAML”的完整攻略。 什么是YAML? YAML是一种轻量级的数据交换格式,它特别适合于人类编辑或查看。与JSON、XML等数据格式相比,它更为简洁、易于理解和编写,而且可以支持嵌套的数据结构。 SnakeYAML是什么? SnakeYAML是一个Java库,提供对YAML的解析和生成。通过Snake…

    Java 2023年5月26日
    00
  • spring boot实现过滤器和拦截器demo

    下面是关于“Spring Boot实现过滤器和拦截器demo”的完整攻略,包含两个示例说明。 Spring Boot实现过滤器和拦截器demo 在Spring Boot中,我们可以使用过滤器和拦截器来对HTTP请求进行处理。本文将详细介绍如何使用Spring Boot来实现过滤器和拦截器。 过滤器 过滤器是一种用于处理HTTP请求和响应的组件,它可以在请求到…

    Java 2023年5月17日
    00
  • Spring boot 整合 Redisson实现分布式锁并验证功能

    下面我将为您讲解“Spring Boot整合Redisson实现分布式锁并验证功能”的完整攻略。 一、Redisson简介 Redisson是一个Java Redis客户端,提供了功能齐全的分布式Redis服务,例如RedLock(分布式锁)、RedQueue(分布式队列)、RedTopic(分布式发布/订阅)等。在很多开源框架中,Redisson也是非常受…

    Java 2023年5月20日
    00
  • JAVA如何把数据库的数据处理成树形结构

    对于将数据库中的数据处理成树形结构,大致可以分为以下三步: 从数据库中获取原始数据 将原始数据转化为树形结构数据 将树形结构数据渲染到前端页面 1.从数据库中获取原始数据 我们首先要从数据库中获取原始数据,一般情况下,我们可以通过使用JDBC操作数据库实现该功能。 示例代码如下: import java.sql.Connection; import java…

    Java 2023年5月20日
    00
  • 如何把char数组转换成String

    将char数组转换成String通常可以使用String类的构造函数方法或valueOf()方法。 使用String类的构造函数方法 示例1: char[] charArray = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’}; String str = new String(charArray); System.out.println(str); /…

    Java 2023年5月26日
    00
  • 荐书|程序员书单必不可少系列之算法篇

    荐书|程序员书单必不可少系列之算法篇 为什么需要学习算法? 算法作为计算机科学中的一门重要学科,是程序员必须掌握的基本功。通俗地说,算法就是解决问题的方法论。学习算法能够帮助程序员更高效地解决复杂的问题,提升程序运行效率,缩短开发时间,从而提高开发竞争力。 学习算法需要哪些书籍? 以下是本人推荐的几本经典算法书籍: 《算法导论》 《算法(第4版)》 《数据结…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部