一分钟使用Java实现socket消息传递

一、目的

       本程序旨在模拟航空器与塔台之间的实时消息传递,展示其在实际航空通讯中的应用。通过使用 Java 的 JFrame 进行图形用户界面(GUI)的设计,以及 socket 编程实现网络通信,该程序能够提供一个直观的界面来显示航空器和塔台之间的信息交换。

二、技术介绍

2.1 JFrame

       JFrame 是 Java 提供的一个顶级容器类,用于创建图形用户界面(GUI)。它是 javax.swing 包的一部分。

2.2 Socket

       Socket 是网络编程中的一个重要概念,代表了网络上的两个节点之间的双向通信端点。Java 提供了 java.net 包来支持 Socket 编程。

2.3 MySQL

       MySQL 是一个开源的关系型数据库管理系统(RDBMS),广泛应用于各种应用程序,从小型项目到大型企业系统。

三、具体实现

3.1 创建数据库

数据库名为 air_traffic

CREATE DATABASE air_traffic;

数据库表明为 messages 。

CREATE TABLE `messages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) COLLATE utf8_bin DEFAULT NULL,
  `message` varchar(255) COLLATE utf8_bin NOT NULL,
  `timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
)

3.2 创建数据库工具类

public class DataBaseUtil {
        // 数据库地址
        private static final String jdbcURL = "jdbc:mysql://localhost:3306/air_traffic";
        // 数据库用户名
        private static final String dbUser = "root";
        // 数据库密码
        private static final String dbPassword = "root123";

        // 保存数据方法
        public static void saveToDatabase(String name, String message) {
                try (Connection connection = DriverManager.getConnection(jdbcURL, dbUser, dbPassword)) {
                        String sql = "INSERT INTO messages (name, message) VALUES (?,?)";
                        PreparedStatement statement = connection.prepareStatement(sql);
                        statement.setString(1, name);
                        statement.setString(2, message);
                        statement.executeUpdate();
                } catch (SQLException e) {
                        e.printStackTrace();
                }
        }
}

3.3 塔台服务

public class ServerHandler extends Thread {
    private BufferedReader in; // 用于读取服务器发送的消息
    private JTextArea displayArea; // 用于在 GUI 中显示消息的文本区域

    // 构造函数,用于初始化 BufferedReader 和 JTextArea
    public ServerHandler(BufferedReader in, JTextArea displayArea) {
        this.in = in;
        this.displayArea = displayArea;
    }

    // 运行方法,负责读取来自服务器的消息并显示在文本区域中
    @Override
    public void run() {
        try {
            String inputLine; // 用于存储每次读取到的消息
            while ((inputLine = in.readLine()) != null) {
                // 显示消息到 JTextArea 中
                displayMessage("塔台: " + inputLine);
                // 将消息保存到数据库
                DataBaseUtil.saveToDatabase("塔台", inputLine);
            }
        } catch (IOException e) {
            e.printStackTrace(); // 捕获并打印 IO 异常
        }
    }

    // 显示消息到 JTextArea 的方法,使用 SwingUtilities.invokeLater 确保线程安全
    private void displayMessage(String message) {
        SwingUtilities.invokeLater(() -> displayArea.append(message + "\n"));
    }
}

3.4 航空器服务

public class ClientHandler extends Thread {
    private Socket clientSocket; // 客户端 socket,用于与服务器通信
    private JTextArea displayArea; // 用于在 GUI 中显示消息的文本区域
    private BufferedReader in; // 用于读取来自客户端的输入流

    // 构造函数,用于初始化 Socket 和 JTextArea
    public ClientHandler(Socket socket, JTextArea displayArea) {
        this.clientSocket = socket;
        this.displayArea = displayArea;
    }

    // 运行方法,负责处理客户端的消息
    @Override
    public void run() {
        try {
            // 初始化 BufferedReader,从客户端的输入流读取数据
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String inputLine; // 用于存储每次读取到的消息
            while ((inputLine = in.readLine()) != null) {
                // 显示消息到 JTextArea 中
                displayMessage("航空器: " + inputLine);
                // 将消息保存到数据库
                DataBaseUtil.saveToDatabase("航空器", inputLine);
            }
        } catch (IOException e) {
            e.printStackTrace(); // 捕获并打印 IO 异常
        } finally {
            // 关闭资源
            try {
                if (in != null) in.close();
                if (clientSocket != null && !clientSocket.isClosed()) clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 显示消息到 JTextArea 的方法,使用 SwingUtilities.invokeLater 确保线程安全
    private void displayMessage(String message) {
        SwingUtilities.invokeLater(() -> displayArea.append(message + "\n"));
    }
}

3.5 塔台窗口

public class AirTrafficControlServer extends JFrame{
    private JTextArea displayArea; // 用于显示消息的文本区域
    private JTextField inputField; // 用于输入消息的文本字段
    private PrintWriter out; // 用于向客户端发送消息的输出流

    // 构造函数,初始化 UI 组件和服务器
    public AirTrafficControlServer() {
        setTitle("塔台"); // 设置窗口标题
        setSize(500, 400); // 设置窗口大小
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭操作

        // 设置窗口背景色为黑色
        UIManager.put("Panel.background", Color.BLACK);
        UIManager.put("TextField.background", Color.BLACK);
        UIManager.put("TextArea.background", Color.BLACK);

        // 设置文本颜色为绿色
        UIManager.put("TextArea.foreground", Color.GREEN);
        UIManager.put("TextField.foreground", Color.GREEN);

        displayArea = new JTextArea(); // 创建用于显示消息的文本区域
        displayArea.setEditable(false); // 文本区域设置为不可编辑
        JScrollPane scrollPane = new JScrollPane(displayArea); // 为文本区域添加滚动条

        inputField = new JTextField(); // 创建用于输入消息的文本字段
        inputField.addActionListener(e -> sendMessage(inputField.getText())); // 为文本字段添加动作监听器

        add(scrollPane, BorderLayout.CENTER); // 将滚动面板添加到窗口中间
        add(inputField, BorderLayout.SOUTH); // 将文本字段添加到窗口底部

        setVisible(true); // 设置窗口可见
        startServer(); // 启动服务器
    }

    // 启动服务器的方法
    private void startServer() {
        Thread serverThread = new Thread(() -> {
            try (ServerSocket serverSocket = new ServerSocket(12345)) { // 创建服务器 socket,监听端口 12345
                while (true) {
                    Socket clientSocket = serverSocket.accept(); // 接受客户端连接
                    out = new PrintWriter(clientSocket.getOutputStream(), true); // 初始化输出流,用于向客户端发送消息
                    new ClientHandler(clientSocket, displayArea).start(); // 创建并启动新的客户端处理线程
                }
            } catch (IOException e) {
                e.printStackTrace(); // 捕获并打印 IO 异常
            }
        });
        serverThread.start(); // 启动服务器线程
    }

    // 发送消息的方法
    private void sendMessage(String message) {
        if (out != null) {
            out.println(message); // 通过输出流向客户端发送消息
            displayMessage("塔台: " + message); // 在文本区域显示发送的消息
            DataBaseUtil.saveToDatabase("塔台", message); // 将消息保存到数据库
        }
        inputField.setText(""); // 清空输入字段
    }

    // 显示消息到文本区域的方法,使用 SwingUtilities.invokeLater 确保线程安全
    private void displayMessage(String message) {
        SwingUtilities.invokeLater(() -> displayArea.append(message + "\n"));
    }
}

3.6 航空器窗口

public class AircraftClient extends JFrame{
    private JTextArea displayArea; // 用于显示消息的文本区域
    private JTextField inputField; // 用于输入消息的文本字段
    private PrintWriter out; // 用于向服务器发送消息的输出流
    private BufferedReader in; // 用于从服务器接收消息的输入流

    // 构造函数,初始化 UI 组件和客户端
    public AircraftClient() {
        setTitle("航空器"); // 设置窗口标题
        setSize(500, 400); // 设置窗口大小
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭操作

        // 设置窗口背景色为黑色
        UIManager.put("Panel.background", Color.BLACK);
        UIManager.put("TextField.background", Color.BLACK);
        UIManager.put("TextArea.background", Color.BLACK);

        // 设置文本颜色为绿色
        UIManager.put("TextArea.foreground", Color.GREEN);
        UIManager.put("TextField.foreground", Color.GREEN);

        displayArea = new JTextArea(); // 创建用于显示消息的文本区域
        displayArea.setEditable(false); // 文本区域设置为不可编辑
        JScrollPane scrollPane = new JScrollPane(displayArea); // 为文本区域添加滚动条

        inputField = new JTextField(); // 创建用于输入消息的文本字段
        inputField.addActionListener(e -> sendMessage(inputField.getText())); // 为文本字段添加动作监听器

        add(scrollPane, BorderLayout.CENTER); // 将滚动面板添加到窗口中间
        add(inputField, BorderLayout.SOUTH); // 将文本字段添加到窗口底部

        setVisible(true); // 设置窗口可见
        startClient(); // 启动客户端
    }

    // 启动客户端的方法
    private void startClient() {
        try {
            Socket socket = new Socket("localhost", 12345); // 创建客户端 socket,连接到服务器的地址和端口
            out = new PrintWriter(socket.getOutputStream(), true); // 初始化输出流,用于向服务器发送消息
            in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 初始化输入流,用于从服务器接收消息
            new ServerHandler(in, displayArea).start(); // 创建并启动新的服务器处理线程
        } catch (IOException e) {
            e.printStackTrace(); // 捕获并打印 IO 异常
        }
    }

    // 发送消息的方法
    private void sendMessage(String message) {
        if (message.equals("7500")) {
            message = "飞机遭遇劫机或者飞机面临劫机危险的紧急情况!!!";
        } else if (message.equals("7600")) {
            message = "通讯故障,通讯失效或者无线电失联状况";
        } else if (message.equals("7700")) {
            message = "飞机出现了紧急情况,包括飞机发生机械故障或有机上人员突发疾病,但并不代表飞机处于危险状况";
        }

        if (out != null) {
            out.println(message); // 通过输出流向服务器发送消息
            displayMessage("航空器: " + message); // 在文本区域显示发送的消息
            DataBaseUtil.saveToDatabase("航空器", message); // 将消息保存到数据库
        }
        inputField.setText(""); // 清空输入字段
    }

    // 显示消息到文本区域的方法,使用 SwingUtilities.invokeLater 确保线程安全
    private void displayMessage(String message) {
        SwingUtilities.invokeLater(() -> displayArea.append(message + "\n"));
    }
}

3.7 塔台登录窗口


public class ServerLoginWindow extends JFrame {
    private JTextField usernameField; // 用于输入用户名的文本字段
    private JPasswordField passwordField; // 用于输入密码的密码字段

    // 构造函数,初始化登录窗口UI组件
    public ServerLoginWindow() {
        setTitle("塔台登录"); // 设置窗口标题
        setSize(300, 200); // 设置窗口大小
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭操作
        setLayout(new GridLayout(3, 2)); // 使用网格布局,3行2列

        JLabel usernameLabel = new JLabel("用户名:"); // 创建用户名标签
        usernameField = new JTextField(); // 创建用于输入用户名的文本字段

        JLabel passwordLabel = new JLabel("密码:"); // 创建密码标签
        passwordField = new JPasswordField(); // 创建用于输入密码的密码字段

        JButton loginButton = new JButton("登录"); // 创建登录按钮
        loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String username = usernameField.getText(); // 获取输入的用户名
                String password = new String(passwordField.getPassword()); // 获取输入的密码
                if (username.equals("admin") && password.equals("123")) { // 验证用户名和密码
                    setVisible(false); // 隐藏登录窗口
                    new AirTrafficControlServer().setVisible(true); // 显示空中交通管制服务器窗口
                } else {
                    JOptionPane.showMessageDialog(ServerLoginWindow.this, "登录失败", "错误", JOptionPane.ERROR_MESSAGE);
                    // 显示登录失败的消息框
                }
            }
        });

        add(usernameLabel); // 将用户名标签添加到窗口
        add(usernameField); // 将用户名文本字段添加到窗口
        add(passwordLabel); // 将密码标签添加到窗口
        add(passwordField); // 将密码密码字段添加到窗口
        add(new JLabel());  // 添加一个占位标签,用于对齐布局
        add(loginButton); // 将登录按钮添加到窗口

        setLocationRelativeTo(null);  // 将窗口显示在屏幕中央
        setVisible(true); // 设置窗口可见
    }

    // 主方法,创建并运行服务器登录窗口实例
    public static void main(String[] args) {
        SwingUtilities.invokeLater(ServerLoginWindow::new); // 在事件调度线程中创建并显示登录窗口
    }
}

3.8 航空器登录窗口

public class ClientLoginWindow extends JFrame {
    private JTextField usernameField; // 用于输入用户名的文本字段
    private JPasswordField passwordField; // 用于输入密码的密码字段

    // 构造函数,初始化登录窗口UI组件
    public ClientLoginWindow() {
        setTitle("航空器登录"); // 设置窗口标题
        setSize(300, 200); // 设置窗口大小
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭操作
        setLayout(new GridLayout(3, 2)); // 使用网格布局,3行2列

        JLabel usernameLabel = new JLabel("用户名:"); // 创建用户名标签
        usernameField = new JTextField(); // 创建用于输入用户名的文本字段

        JLabel passwordLabel = new JLabel("密码:"); // 创建密码标签
        passwordField = new JPasswordField(); // 创建用于输入密码的密码字段

        JButton loginButton = new JButton("登录"); // 创建登录按钮
        loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String username = usernameField.getText(); // 获取输入的用户名
                String password = new String(passwordField.getPassword()); // 获取输入的密码
                if (username.equals("001") && password.equals("123")) { // 验证用户名和密码
                    setVisible(false); // 隐藏登录窗口
                    new AircraftClient().setVisible(true); // 显示航空器客户端窗口
                } else {
                    JOptionPane.showMessageDialog(ClientLoginWindow.this, "登录失败", "错误", JOptionPane.ERROR_MESSAGE);
                    // 显示登录失败的消息框
                }
            }
        });

        add(usernameLabel); // 将用户名标签添加到窗口
        add(usernameField); // 将用户名文本字段添加到窗口
        add(passwordLabel); // 将密码标签添加到窗口
        add(passwordField); // 将密码密码字段添加到窗口
        add(new JLabel());  // 添加一个占位标签,用于对齐布局
        add(loginButton); // 将登录按钮添加到窗口

        setLocationRelativeTo(null);  // 将窗口显示在屏幕中央
        setVisible(true); // 设置窗口可见
    }

    // 主方法,创建并运行客户端登录窗口实例
    public static void main(String[] args) {
        SwingUtilities.invokeLater(ClientLoginWindow::new); // 在事件调度线程中创建并显示登录窗口
    }
}

四、运行展示

登录页面

消息传递

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/699065.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1、链接(link)

链接的作用 链接:将各种代码和数据片段收集组成一个单一文件的过程,这个文件可以加载(复制)到内存并执行。 分为:编译时、加载时(加载器加载到内存并执行时)、运行时 1、构造大型程序 2、避免…

Python魔法之旅-魔法方法(22)

目录 一、概述 1、定义 2、作用 二、应用场景 1、构造和析构 2、操作符重载 3、字符串和表示 4、容器管理 5、可调用对象 6、上下文管理 7、属性访问和描述符 8、迭代器和生成器 9、数值类型 10、复制和序列化 11、自定义元类行为 12、自定义类行为 13、类型检…

【数学】927. 三等分

本文涉及知识点 数学 LeetCode927. 三等分 给定一个由 0 和 1 组成的数组 arr &#xff0c;将数组分成 3 个非空的部分 &#xff0c;使得所有这些部分表示相同的二进制值。 如果可以做到&#xff0c;请返回任何 [i, j]&#xff0c;其中 i1 < j&#xff0c;这样一来&#…

消费增值模式引领业绩飙升与用户活跃

大家好&#xff0c;我是吴军&#xff0c;致力于为您揭示私域电商领域的独特魅力与机遇。 今日&#xff0c;我很高兴与大家分享一个激动人心的成功案例。我们的客户在短短一个月的时间里&#xff0c;业绩就飙升至上百万级别&#xff0c;其用户活跃度更是居高不下&#xff0c;日…

如何进行考试成绩分析

一、为什么要对考试成绩进行分析&#xff1f; 考试成绩进行分析是一项重要的工作&#xff0c;可以为学生、教师和学校提供有效的学习评价和支持&#xff0c;同时也可以为教学改进和提高教学质量提供有力的支持和指导。对考试成绩进行分析有以下几个原因&#xff1a; 1.了解学生…

Keil一键添加.c文件和头文件路径脚本--可遍历添加整个文件夹

最近想移植个LVGL玩玩&#xff0c;发现文件实在是太多了&#xff0c;加的手疼都没搞完&#xff0c;实在不想搞了就去找脚本和工具&#xff0c;基本没找到一个。。。。。。 主要是自己也懒得去研究写脚本&#xff0c;偶然搜到了一个博主写的脚本&#xff0c;原博客地址:https:/…

【鸿蒙开发教程】HarmonyOS 模块关系梳理

HarmonyOS 梳理模块关系 刚开始开发的时候总是理不清鸿蒙中的模块类型和关系&#xff0c;今天就来梳理下鸿蒙中的模块类型 Module类型 Module按照使用场景可以分为两种类型&#xff1a; ●Ability类型的Module&#xff1a; 用于实现应用的功能和特性。每一个Ability类型的M…

西南交通大学【操作系统实验2】

实验目的 本实验要求学生了解什么是信号&#xff0c;掌握软中断的基本原理&#xff1b;掌握中断信号的使用、进程的创建以及系统计时器的使用。通过对本实验的学习&#xff0c;学生能够学会进程的创建方法&#xff0c;更能加深对Linux中的信号机制的认识&#xff0c;并会使用软…

《银行存量客户运营》导读

前言&#xff1a;在中国生活&#xff0c;没有一个人能够离得开银行&#xff0c;但是又有多少人真正了解银行呢&#xff1f; 通过本书你可以学习到&#xff1a;银行不为外人了解的内部运营机制&#xff0c;甚至可以提前把握银行涨息降息政策规律 银行运营的基础逻辑 “运营”二…

泉城济南的隐秘珍宝与山东旅游必去十大景点

泉城济南的隐秘珍宝与山东旅游必去十大景点 济南&#xff0c;这座历史悠久的城市&#xff0c;不仅以其丰富的人文底蕴著称&#xff0c;还拥有诸多引人入胜的自然景观。在这片华夏神州广阔的齐鲁大地上&#xff0c;济南特别以其“三无风景区”——无影山、无影潭、无影泉——而闻…

ON DUPLICATE KEY UPDATE 子句

ON DUPLICATE KEY UPDATE 是 MySQL 中的一个 SQL 语句中的子句&#xff0c;主要用于在执行 INSERT 操作时处理可能出现的重复键值冲突。当尝试插入的记录导致唯一索引或主键约束冲突时&#xff08;即试图插入的记录的键值已经存在于表中&#xff09;&#xff0c;此子句会触发一…

neo4j 3.5.5版本创建新的数据库

neo4j 3.5.5版本创建新的数据库 1.找到neo4j的conf文件 点进去 2.点击neo4j.conf 选择记事本打开 3.把graph.db换成自己想要创建的数据库名称 4.打开neo4j服务 出现新的数据库

AI Agent 热门的10篇论文

人工智能代理领域广阔,涵盖广泛的主题,包括多代理系统、强化学习、上下文感知系统以及将大型语言模型 (LLMs) 集成到基于代理的系统中。以下是 arXiv 的一些顶级论文,涵盖了人工智能代理的各个方面: A Framework For Intelligent Multi Agent System Based Neural Network …

rman恢复后,少部分数据文件状态为MISSING000**

客户有套一体机&#xff0c;每天晚上21点开始做rman完全备份&#xff0c;大约第2天上午9点多完成备份&#xff0c;rman备份保留策略保留一份完全备份 6月1日晚21点自动发起备份&#xff0c;6月2日上午10点15分完成备份&#xff0c;并生成了一个控制文件备份 c-4063271871-2024…

量产导入 | KGD 是什么?

文章目录 KGD 是什么&#xff1f;认识KGD定义、功能与应用实例【白话文解析】Known Good「Die」何谓良品裸晶粒 &#xff08;KGD/KGD Die&#xff09;&#xff1f;解读KGD产业应用为什么大家纷纷采用KGD&#xff1f; 一窥KGD与芯片封测大趋势 KGD 是什么&#xff1f;认识KGD定义…

【Linux系统】线程与线程控制

本篇博客整理了Linux下线程的概念、线程控制的相关接口&#xff0c;旨在让读者初步认识线程&#xff0c;并为下一篇多线程作铺垫。 目录 一、线程是什么 1.线程是进程的执行流 2.线程的执行、调度、切换 3.页表分级与线程资源分配 4.线程的优缺点 二、线程控制 1.创建…

mmdeploy环境部署流程

参考&#xff1a;mmdeploy/docs/zh_cn/01-how-to-build/linux-x86_64.md at main open-mmlab/mmdeploy (github.com) 从零入门《openmmlab》mmdeploy[1]环境安装及简单上手_哔哩哔哩_bilibili 我的环境&#xff1a; docker容器&#xff0c;ubuntu20.04&#xff0c;cuda11.7…

【万方数据库爬虫简单开发(自用)】

万方数据库爬虫简单开发&#xff08;自用&#xff09;&#xff08;一&#xff09; 使用Python爬虫实现万方数据库论文的搜索并获取信息1.获取url2.输入关键词3.使用BeautifulSoup解析4.获取文章标题信息 使用Python爬虫实现万方数据库论文的搜索并获取信息 后续会逐步探索更新…

从盛世到衰落,历史上八大强国的兴衰与现代地位!

人类文明史悠久&#xff0c;从远古时代至今日&#xff0c;世界舞台上曾经涌现出许多强盛的帝国。它们在自己的黄金时代&#xff0c;曾经无人能敌&#xff0c;不论是在军事、经济还是文化上都独领风骚。然而&#xff0c;无论多么强大的国家也难逃“兴盛必衰”的命运。今天&#…

javaWeb项目-在线考试系统详细功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Java简介 Java语…