Java利用UDP实现简单群聊

一、创建新项目
首先新建一个新的项目,并按如下操作

二、实现代码
界面ChatFrame类
package 群聊;
 
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.InetAddress;
 
public abstract class ChatFrame extends JFrame {
    private JTextArea receiveArea = new JTextArea();//接收文本框,用来显示服务器发送过来的文本
    private JTextArea sendArea = new JTextArea();//发送文本框,用来显示当前用户要发送的文本
 
    private JButton sendBtn = new JButton("SEND");//发送按键
 
    public ChatFrame() {
        this.initFrame();//初始化窗口
        this.initComponent();//初始化组件
        this.initListener();//初始化监听器
        this.receive();//开启监听服务器线程,把接收到的文本显示在receiveArea中
    }
 
    // 初始化监听器
    private void initListener() {
        // 给发送按键添加监听器,当被点击时调用send()方法
        sendBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                send();
            }
        });
 
        // 给发送文本框添加键盘监听器,当按下Ctrl+ENTER时调用send()方法
        sendArea.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if(e.isControlDown()) {
                    if(e.getKeyCode() == KeyEvent.VK_ENTER) {
                        send();
                    }
                }
            }
        });
    }
 
    // 子类需要重写本方法
    // 在本方法中使用socket实现消息发送
    public abstract void sendText(String text);
 
    // 子类需要重写本方法
    // 在本方法中启动监听服务器线程,调用本类receiveText(String)把接收到的文本显示出来
    public abstract void receive();
 
    // 本方法用来发送文本
    public void send() {
        // 如果发送文本框中没有文本,弹出警告对话框
        if(sendArea.getText().equals("")) {
            javax.swing.JOptionPane.showMessageDialog(this, "空文本不能发送!");
            sendArea.requestFocus();// 把光标归还给发送文本框
            return;
        }
 
        // 调用子类的方法完成文本发送
        sendText(sendArea.getText());
        // 把发送文本框内容清空
        sendArea.setText(null);
    }
 
    // 本方法完成接收服务器消息的后续工作-在文本框中显示服务器消息,子类的receive()方法在接收服务器消息后可以调用本方法
    public void receiveText(String text) {
        receiveArea.append(text);//把接收到的消息添加到文本框中
        // 设置光标位置到最后,如果不设置滚动条不动
        receiveArea.setCaretPosition(receiveArea.getText().length());
    }
 
    // 初始化组件
    private void initComponent() {
        // 使用接收文本框创建滚动窗口(把文本框添加到了滚动窗口中),总是显示纵向滚动条,永不显示横向滚动条
        JScrollPane sp1 = new JScrollPane(receiveArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        // 设置滚动窗口大小、位置、无边框;并把滚动窗口添加到主窗口中
        sp1.setSize(606, 350);
        sp1.setLocation(14, 20);
        sp1.setBorder(null);
        this.add(sp1);
 
        // 设置接收文本框背景色、不可编辑、自动换行
        receiveArea.setBackground(new Color(238, 238, 238));
        receiveArea.setEditable(false);
        receiveArea.setLineWrap(true);
 
        // 创建发送文本框的滚动窗口,设置自动换行、大小、位置,然后添加到主窗口中
        JScrollPane sp2 = new JScrollPane(sendArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        sendArea.setLineWrap(true);
        sp2.setSize(606, 145);
        sp2.setLocation(14, 400);
        this.add(sp2);
 
        // 设置发送按键的大小、位置,并添加到主窗口中
        sendBtn.setSize(68, 21);
        sendBtn.setLocation(553, 560);
        this.add(sendBtn);
 
        // 设置主窗口的标题为当前IP地址
        try {
            this.setTitle(InetAddress.getLocalHost().getHostAddress());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
 
    // 初始化主窗口
    private void initFrame() {
        // 设置主窗口的大小、布局管理器为空、背景色、位置、大小不可改变
        this.setSize(640, 620);
        this.setLayout(null);
        this.setBackground(new Color(246, 246, 247));
        this.setLocation(350, 50);
        this.setResizable(false);
 
        // 设置主窗口的“X”按钮点击后结束程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
 
    // 显示主窗口方法
    public void setVisible(boolean b) {
        super.setVisible(b);//调用父类的显示方法
        sendArea.requestFocus();//让发送文本框得到焦点
    }
}

组播聊天SocketChat类
package 群聊;
 
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Date;
 
/**
 * 本类继承了ChatFrame,ChatFrame实现了GUI显示
 * 本类负责使用MulticastSocket完成群聊的发送消息与接收消息
 */
public class SocketChat extends ChatFrame {
    private MulticastSocket socket;//群组Socket
 
    public SocketChat() throws IOException {
        socket = new MulticastSocket(54321);//创建群组Socket,绑定54321端口
        //加入虚拟IP:235.235.235.235指定的群组中。虚拟IP范围是:224.0.0.1 和 239.255.255.255
        //加入群组后,就可以接收群组的消息,也可以向群组发送消息了
        socket.joinGroup(InetAddress.getByName("235.235.235.235"));
    }
 
    // 发送消息方法
    public void sendText(String text) {
        try {
            // 获取IP地址
            String ip = InetAddress.getLocalHost().getHostAddress();
            // 获取当前时间格式化字符串
            String time = String.format(" <====> %tF %<tT", new Date());
            // 把IP、时间,以及要发送的文本连接在一起
            text = ip + time + "\n" + text + "\n\n";
            // 把文本转换成字节数组
            byte[] buff = text.getBytes();
            // 使用socket向群组发送,socket的send()方法需要两个参数:DatagramPacket、端口号
            // DatagramPacket表示数据包,创建它需要三个参数:数据包的内容、数据包的字节数、要发送的IP地址
            socket.send(new DatagramPacket(buff, buff.length, InetAddress.getByName("235.235.235.235"), 54321));
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
 
    // 本方法用来接收群组发送过来的消息
    public void receive() {
        // 创建监听群组消息的线程,并启动它
        new Thread() {
            public void run() {
                // 循环监听
                while(true) {
                    try {
                        // 创建数据包的字节数组,大小为1KB
                        byte[] buff = new byte[1024];
                        // 创建数据包
                        DatagramPacket dp = new DatagramPacket(buff, buff.length);
                        // 接收群组发送过来的消息到数据包中
                        // 本方法会阻塞当前线程,直到接收到消息为止
                        socket.receive(dp);
                        // 把接收到的消息转换成字符串
                        String text = new String(dp.getData(), 0, dp.getLength());
                        // 调用父类的方法完成显示
                        receiveText(text);
                    } catch(Exception e) {}
                }
            }
        }.start();
    }
 
    public static void main(String[] args) throws IOException {
        SocketChat sc = new SocketChat();
        sc.setVisible(true);
    }
}

三、运行结果


运行的第一个窗口成员1

第二个窗口为成员2

第三个窗口为成员3

由此可见、新建窗口=添加成员
 

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

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

相关文章

决策树 (人工智能期末复习)

几个重要概念 信息熵&#xff1a;随机事件未按照某个属性的不同取值划分时的熵减去按照某个属性的不同取值划分时的平均 熵。即前后两次熵的差值。 表示事物的混乱程度&#xff0c;熵越大表示混乱程度越大&#xff0c;越小表示混乱程度越小。 对于随机事件&#xff0c;如果它的…

推荐一款Excel快速加载SQL的插件,方便又好用

如果告诉你只需要双击一下&#xff0c;SQL数据库中存放在表里面的数据&#xff0c;就能加载到你的Excel中&#xff0c;你想不想要&#xff1f; 今天给大家推荐一款好用的Excel插件&#xff0c;安装简单&#xff0c;使用方便&#xff0c;是经常使用SQL数据库的不二。 这款插件…

ANYTEXT: MULTILINGUAL VISUAL TEXT GENERATION AND EDITING

ANYTEXT: MULTILINGUAL VISUAL TEXT GENERATION AND EDITING Yuxiang Tuo, Institute for Intelligent Computing, Alibaba Group, ICLR2024 (6668), Code, Paper 1. 前言 基于扩散模型的文本到图像最近取得了令人印象深刻的成就。尽管当前用于合成图像的技术是高度先进的&am…

大话数据结构-查找-有序表查找

注&#xff1a;本文同步发布于稀土掘金。 3 有序表查找 3.1 折半查找 折半查找&#xff08;Binary Search&#xff09;技术&#xff0c;又称为二分查找&#xff0c;它的前提是线性表中的记录必须是关键码有序&#xff08;通常从小到大有序&#xff09;&#xff0c;线性表必须…

助力信创自主可控,AntDB与浪潮、超聚变完成产品互认

日前&#xff0c;湖南亚信安慧科技有限公司与浪潮商用机器有限公司、超聚变数字技术有限公司展开产品兼容互认工作。 近年来&#xff0c;在数据处理需求快速增长以及信创政策加持的情况下&#xff0c;信创行业活力迸发。操作系统、数据库和服务器作为信创基础软硬件&#xff0…

idea编辑代码卡顿问题

现象&#xff1a; 日常开发代码的时候&#xff0c;偶尔会遇到开发某个项目的时候&#xff0c;一编辑代码就会idea就会卡住 定位&#xff1a; 1、不敲代码时&#xff0c;电脑性能一切正常 2、只要一修改代码&#xff0c;可以发现cpu老是飙到100 3、但是相同的一个项目&#x…

Ubuntu22.04通过Maas和Juju部署openstack charm

目录 官方文档材料准备软件硬件 模板机和虚拟网络安装MAAS官方文档MAAS节点配置安装MAAS浏览器登录MAAS进行配置 激活DHCP 官方文档 https://docs.openstack.org/project-deploy-guide/charm-deployment-guide/2023.1/ 这是一个通过Maas面板即可部署openstack的方式&#xff0…

python HTML文件标题解析问题的挑战

引言 在网络爬虫中&#xff0c;HTML文件标题解析扮演着至关重要的角色。正确地解析HTML文件标题可以帮助爬虫准确地获取所需信息&#xff0c;但是在实际操作中&#xff0c;我们常常会面临一些挑战和问题。本文将探讨在Scrapy中解析HTML文件标题时可能遇到的问题&#xff0c;并…

Spring Boot基础

文章目录 一、Spring Boot1. Spring的缺点2. Spring Boot 改变了什么3. Spring Boot项目搭建4. 热部署5. 依赖管理6. 代码生成器7. 日志8. 日期转换9. 接口文档10. 打包部署11. 自动装配 一、Spring Boot 1. Spring的缺点 在Spring Boot出现以前&#xff0c;使用Spring框架的…

Windows系统的Chkdsk(磁盘修复工具),好用快速的磁盘医生

一款非常具有专业性、权威的工具,可以全面的检测电脑的硬盘坏道,标记出来并且进行及时的修复,它还可以对移动硬盘等进行检测修复。chkdsk还可以支持目前流行的各种系统文件格式,例如:FAT、FAT32、NTFS等。还可以针对坏道磁盘错误进行深度优化,保证电脑磁盘的安全和完整性…

这是聊天阿!this (酸萝卜别吃)doge

1——on——1 chat 服务端 package work; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.util.ArrayList; import java.util.List;public class UDPServer {private static final int PORT 9876;private static List<ClientInf…

新生报到管理系统

【摘要】 随着我国教育水平的提高和新生数量的增加&#xff0c;合理妥善高效的进行新生接待&#xff0c;不但成为各个学校亟待解决的问题&#xff0c;对于广大新生来说&#xff0c;也是最先让他们了解学校形象的一个好机会。但是许多学校没有采用通过高效的系统来操作解决新生…

吉利护航,宣称比友商“更懂车”,魅族造车的底气与底色

继小米、华为后&#xff0c;又一家手机厂商宣布跨界造车。 在近日举办的2023魅族秋季无界生态发布会上&#xff0c;星纪魅族集团&#xff08;下称“魅族”&#xff09;董事长兼CEO沈子瑜宣布&#xff0c;魅族正式进入汽车市场&#xff0c;将在2024年第一季度启动“DreamCar共创…

pyqt5+QWebEngineView+pdfjs+win32print实现pdf文件的预览、打印

一、pdf显示逻辑 import sys from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgetsPDFJS = file:///pdfjs-1.9.426-dist/web/viewer.html # PDFJS = file:///usr/share/pdf.js/web/viewer.html PDF = file:///D:/Code/report.pdfclass Window(QtWebEngineWidgets.QWebEng…

大话数据结构-查找-散列表查找(哈希表)

注&#xff1a;本文同步发布于稀土掘金。 8 散列表查找&#xff08;哈希表&#xff09; 8.1 定义 散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f&#xff0c;使得每个关键字key对应一个存储位置f(key)。查找时&#xff0c;根据这个确定的对应关系找到给…

Python Collections库的高级功能详解

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Python的collections库提供了一系列有用的数据类型&#xff0c;扩展了内建的数据类型&#xff0c;为开发者提供了更多高级功能。本文将深入探讨collections库的一些高级功能&#xff0c;通过详细的示例代码演示&…

北森2023半年报洞察:中国HCM SaaS市场的未来,只能是北森

作者 | 曾响铃 文 | 响铃说 中国的HCM SaaS市场处在了一个不尴不尬的状态&#xff0c;尽管前景广阔&#xff0c;但是需求却迟迟未能爆发&#xff0c;整体行业卡在了一个明显的瓶颈期。 其中&#xff0c;又以北森的处境最为典型。 根据IDC发布的《IDC中国人力资本管理&#…

EDW国际数据管理最新趋势(二)|信息供应链与数据

最近Data Fabric、Data Mesh、DataOps等话题非常火。其实&#xff0c;信息供应链谈的也是同样的东西&#xff0c;那就是如何将数据治理与数据集成整合在一起的解决方案。 下图虽然简单但涵盖了非常大的信息量。将4A架构进行了拆解&#xff0c;应用架构与技术架构主要是支撑业务…

AOP记录操作日志

创建数据库表 -- 操作日志 create table operate_log (id int unsigned primary key auto_increment commentid,operate_user int unsigned comment 操作人员Id,operate_time datetime comment 操作时间,class_name varchar(100)comment 操作类,method_name varchar(100)comme…

IDEA 修改encoding

IDEA 修改encoding 现象&#xff1a;idea展示乱码 打开Settings>>File Encodings&#xff0c;修改为UTF-8即可