基于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日

相关文章

  • Java利用HttpClient模拟POST表单操作应用及注意事项

    Java利用HttpClient模拟POST表单操作应用及注意事项 前言 在实现Java程序中模拟POST表单操作时,HttpClient是一个非常常用的工具。本文将介绍HttpClient的基本使用方法,以及在模拟POST表单操作时需要注意的一些细节。 HttpClient是什么 HttpClient是一个基于Http协议的开源库,可以通过HttpClie…

    Java 2023年5月19日
    00
  • java实战小技巧之优雅的实现字符串拼接

    下面是关于”Java实战小技巧之优雅的实现字符串拼接”的攻略。 背景 字符串拼接是Java开发中比较基础的操作之一,但是在不注意的情况下,随意的字符串拼接方式可能会导致代码的可读性和可维护性下降。因此,在进行Java开发时,需要注意如何优雅地实现字符串拼接,提高代码的可读性、可维护性和效率。 方式一:使用StringBuilder 在Java中,字符串拼接的…

    Java 2023年5月26日
    00
  • 闲言碎语-逐步了解Spring

    当我们开始学习 Spring 的时候,我们经常会被各种概念和组件迷惑。为了逐步了解 Spring,以下是一些基本步骤: 1. 了解Spring的核心概念 在学习 Spring 之前,需要先了解 Spring 的基础概念。以下是一些常见的 Spring 核心概念: 依赖注入(Dependency Injection,DI) 依赖注入是 Spring 框架的核心…

    Java 2023年5月19日
    00
  • Java异步编程的作用是什么?

    Java异步编程是指在处理高并发、大量请求的情况下,通过异步方式来实现更高的效率和性能。异步编程主要是通过异步操作来实现,异步操作是指当一个请求发出后,不必等待该请求完全响应后再去处理下一个请求,而是可以立即处理下一个请求,并在响应返回后再对其进行处理。 Java异步编程利用了多线程技术,将一个请求分为多个阶段,每个阶段使用一个线程单独处理,并在所有阶段都完…

    Java 2023年5月11日
    00
  • mybatis框架入门学习教程

    下面我将详细讲解”mybatis框架入门学习教程”的完整攻略,该攻略包括以下几个部分: 一、Mybatis框架概述 Mybatis是一个开源的持久层框架,它支持自定义SQL、存储过程调用和高级映射,可以将结果集映射到Java对象中。它主要有以下优点: SQL与程序解耦:Mybatis的SQL存放在XML文件中,与Java程序相分离,使程序易于维护。 灵活性高…

    Java 2023年5月19日
    00
  • JSP开发中hibernate框架的常用检索方式总结

    JSP开发中Hibernate框架的常用检索方式总结 在Java Web开发中,使用Hibernate框架来操作数据库是非常常见的。有时候我们需要进行数据检索,本篇文章将总结Hibernate中常用的检索方式。 HQL Hibernate Query Language,简称HQL,是Hibernate提供的一种面向对象的检索语言。 基本查询 from Ent…

    Java 2023年6月15日
    00
  • Spring Native打包本地镜像的操作方法(无需通过Graal的maven插件buildtools)

    Spring Native打包本地镜像的操作方法 简介 Spring Native是Spring团队推出的一款可以将Java代码编译成本地可执行二进制文件的工具,在性能、启动速度等方面拥有很大的优势。本文主要介绍如何使用Spring Native将Java应用打包成本地镜像。 环境准备 在开始之前,需要确保以下工具已经安装好并配置: Docker Java …

    Java 2023年6月2日
    00
  • eclipse怎么实现java连oracle数据库?

    要在Eclipse中使用Java连接Oracle数据库,需要完成以下步骤: 步骤一:安装Oracle JDBC驱动程序 在Eclipse中连接Oracle数据库,需要下载并安装Oracle JDBC驱动程序。 下载最新的Oracle JDBC驱动程序,例如ojdbc6.jar或ojdbc8.jar。 将下载的jar文件复制到Eclipse项目的/libs目录…

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