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
由此可见、新建窗口=添加成员
相关文章:

Java利用UDP实现简单群聊
一、创建新项目 首先新建一个新的项目,并按如下操作 二、实现代码 界面ChatFrame类 package 群聊; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.net.InetAddress; public abstract class ChatFrame extends JFrame { p…...

fastapi.templating与HTMLResponse
要声明一个模板对象,应将存储html模板的文件夹作为参数提供。在当前工作目录中,我们将创建一个 “templates “目录。 templates Jinja2Templates(directory“templates”) 我们现在要把这个页面的HTML代码渲染成HTMLResponse。让我们修改一下hello()函…...
当初为什么选择计算机这类的行业?
CSDN给了这么一个话题: 还记得当初自己为什么选择计算机? 当初你问我为什么选择计算机,我笑着回答:“因为我梦想成为神奇的码农!我想像编织魔法一样编写程序,创造出炫酷的虚拟世界!”谁知道&…...
tif文件转png、Excel
l利用gdal读取tif中的地理信息和波段数组,然后保存想要的格式即可。 from osgeo import gdal from PIL import Image import numpy as np import cv2 as cv from matplotlib import pyplot as plt# 读取.tif文件 def read_tif(file_path):dataset gdal.Open(file_…...

【PyTorch】训练过程可视化
文章目录 1. 训练过程中的可视化1.1. alive_progress1.2. rich.progress 2. 训练结束后的可视化2.1. tensorboardX2.1.1. 安装2.1.2. 使用 1. 训练过程中的可视化 主要是监控训练的进度。 1.1. alive_progress 安装 pip install alive_progress使用 from alive_progress i…...

深入理解Go语言GC机制
1、Go 1.3之前的标记-清除(mark and sweep)算法 Go 1.3之前的时候主要用的是普通的标记-清除算法,此算法主要由两个主要的步骤: 标记(Mark phase)清除(Sweep phase) 1)…...

qt-C++笔记之组件-分组框QGroupBox
qt-C笔记之组件-分组框QGroupBox code review! 文章目录 qt-C笔记之组件-分组框QGroupBox1.《Qt 6 C开发指南》p752.《Qt 官方文档》3.《Qt 5.12实战》——5.9 分组框控件 1.《Qt 6 C开发指南》p75 2.《Qt 官方文档》 中间段落翻译: 我把示例补充完整: …...
qt 定时器用法
在qt开发中,定时器是我们经常用到的。我们接下来说一下定时器的三种用法,需要注意的是定时器事件是在主线程中触发的,因此在处理耗时操作时应特别小心,以避免阻塞应用程序的事件循环。 1. 三种定时器使用 1.1 QObject的定时器 …...

用23种设计模式打造一个cocos creator的游戏框架----(九)访问者模式
1、模式标准 模式名称:访问者模式 模式分类:行为型 模式意图:将数据操作与数据结构分离,使得在不修改数据结构的前提下,可以添加或改变对数据的操作。 结构图: 适用于: 当你需要对一个复杂对…...

根文件系统初步测试
一. 简介 上一篇文章学习了向所编译生成的根文件系统中加入 lib库文件。文章地址如下: 根文件系统lib库添加与初步测试-CSDN博客 本文继上一篇文章的学习,本文对之前制作的根文件系统进行一次初步测试。 二. 根文件系统初步测试 为了方便测试&#…...

【精选】设计模式——策略设计模式-两种举例说明,具体代码实现
Java策略设计模式 简介 策略设计模式是一种行为型设计模式,它允许在运行时选择算法的行为。 在软件开发中,我们常常需要根据不同情况采取不同的行为。通常的做法是使用大量的条件语句来实现这种灵活性,但这会导致代码变得复杂、难以维护和扩…...

外包干了3个月,技术倒退2年。。。
先说情况,大专毕业,18年通过校招进入湖南某软件公司,干了接近6年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...
微信小程序:chooseimage从本地相册选择图片或使用相机拍照
文档 https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html 代码示例 const res await uni.chooseImage({count: 1, //默认9sizeType: [original, compressed], //可以…...

「Swift」取消UITableView起始位置在状态栏下方开始
前言:在写页面UI时发现,当隐藏了NavigationBar时,即使UITableView是从(0,0)进行布局,也会一直在手机状态栏下方进行展示布局,而我的想法是希望UITableView可以从状态栏处就进行展示布局 当前页面展示: 问题…...
android高版本适配使用Tools.java
随着android版本的提升,原生Tools不公开并且不能被正常使用,为了延续项目的功能,修改如下: /** Copyright (C) 2006 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License&quo…...

面试官:说说webpack中常见的Loader?解决了什么问题?
面试官:说说webpack中常见的Loader?解决了什么问题? 一、是什么 loader 用于对模块的"源代码"进行转换,在 import 或"加载"模块时预处理文件 webpack做的事情,仅仅是分析出各种模块的依赖关系&a…...

【蓝桥杯省赛真题50】Scratch智能计价器 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解
目录 scratch智能计价器 一、题目要求 编程实现 二、案例分析 1、角色分析...
折半查找(数据结构实训)
题目: 标准输入输出 题目描述: 实现折半查找。要求查找给定的值在数据表中相应的存储位置。本题目假定输入元素均按非降序输入。 输入: 输入包含若干个测试用例,第一行为测试用例个数k。每个测试用例占3行,其中第一行为…...

AR助推制造业智能转型:实时远程协作与可视化引领生产创新
制造商面临着多方面的变革,技术的兴起催生了工业物联网(IIoT),改变了现代工厂的外貌、系统和流程。同时,全球竞争压力和不断变化的员工队伍要求采用新的员工培训方法,并重新审视工人在工厂中的角色。尽管如…...

【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇3(附项目源码)
文章目录 本节最终效果前言素材人物移动音效枪口火焰和开火音效枪口灯光弹孔和火花添加武器随镜头手臂摇摆效果源码完结 本节最终效果 前言 本节主要实现添加音效,和一些特效、武器摆动调整。 素材 素材,为了方便我直接用了unity免费的音效输出&#…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...

Redis专题-实战篇一-基于Session和Redis实现登录业务
GitHub项目地址:https://github.com/whltaoin/redisLearningProject_hm-dianping 基于Session实现登录业务功能提交版本码:e34399f 基于Redis实现登录业务提交版本码:60bf740 一、导入黑马点评后端项目 项目架构图 1. 前期阶段2. 后续阶段导…...

Python 解释器安装全攻略(适用于 Linux / Windows / macOS)
目录 一、Windows安装Python解释器1.1 下载并安装Python解释1.2 测试安装是否成功1.3 设置pip的国内镜像------永久配置 二、macOS安装Python解释器三、Linux下安装Python解释器3.1 Rocky8.10/Rocky9.5安装Python解释器3.2 Ubuntu2204/Ubuntu2404安装Python解释器3.3 设置pip的…...
n8n:解锁自动化工作流的无限可能
在当今快节奏的数字时代,无论是企业还是个人,都渴望提高工作效率,减少重复性任务的繁琐操作。而 n8n,这个强大的开源自动化工具,就像一位智能的数字助手,悄然走进了许多人的工作和生活,成为提升…...