【Java教程】UDP实现群聊聊天室

article/2025/10/23 5:34:55

大家好,今天为大家带来了一个非常有意思的小程序——UDP实现的群聊聊天室。这个程序使用的UDP协议,并使用DatagramSocket的子类MulticastSocket实现组播,可以部署在一个局域网内的多台电脑上,并可以实现文字群聊。

本文将会按照以下几个小节讲解:

1). 组播的概念:这个小节我们将讲解什么是:单播、广播、组播。

2). MulticastSocket类的使用:这个小节我们将讲解MulticastSocket类的基本使用,并实现控制台的信息收发。

3). 基于Swing和MulticastSocket实现的UDP群聊聊天室:这个小节我们将制作一个界面,并结合MulticastSocket类实现一个完整的UDP群聊聊天室。

4). 结束语:

一、组播的概念

网络数据传播按照接收者的数量,可分为以下3种方式:

1.1 单播:

单播是指实现“点对点”的通信,发送者发送数据要发送给网络上的唯一的一台电脑,指定一个接收者。像TCP协议和UDP协议都能实现点对点通信。

1.2 广播:

发送者发送的数据可以被某个接收范围内所有的接收者接收。它类似于广播电台,向某个范围内的所有用户发送广播信号,接收人打开广播就可以听到,关闭广播设备就停止收听。由于广播会大大增加网络数据流量,所以通常情况下一些网络路由器会禁止广播数据,尤其是一些占用网络资源比较大的视频数据等。

1.3 组播:

组播是指发送的数据可以被指定的一组用户接收。组播的范围没有广播那么广,任何的一台电脑都可以随时加入某一个组接收组播数据。若要使用组播,则需要让一个数据报标有一组目标主机地址,当数据报发出后,整个组的所有主机都能收到该数据报。IP协议为组播提供了这批特殊的IP地址,这些IP地址的范围是224.0.0.0至239.255.255.255。在Java类库中,DatagramSocket有一个子类:MulticastSocket,它具有组播的功能,它可以与DatagramPackage结合使用,用于发送和接收组播包。

二. MulticastSocket类的使用

Java类库中MulticastSocket类可以实现组播功能,它是DatagramSocket的子类:

2.1 构造方法说明

通过API文档我们可以看到它有三个构造方法:

1. MulticastSocket() 创建一个多播套接字。(使用随机端口,如果只发送,可以使用这个构造方法)
2. MulticastSocket(int port) 创建一个多播套接字并将其绑定到一个特定的端口。(如果需要发送和接收,需要使用这个构造方法)
3. MulticastSocket(SocketAddress bindaddr) 创建一个多播套接字绑定到指定的套接字地址。

2.2 成员方法说明

以下是几个比较重要的成员方法:

1.public void joinGroup(InetAddress mcastaddr):将该MulticastSocket加入指定的多点广播地址。
2.public void leaveGroup(InetAddress mcastaddr让该MulticastSocket离开指定的多点广播地址。
3.public void setInterface(InetAddress inf):如果当前系统有多个网络接口,可以使用次方法指定一个网络接口。
4.public InetAddress getInterface():获取当前的网络接口。
5.public void setTimeToLive(int ttl):该参数设置数据报最多可以跨过多少个网络,当ttl为0时,指定数据报应停留在本地主机;当ttl的值为1时,指定数据报发送到本地局域网;当ttl的值为32时,意味着只能发送到本站点的网络上;当ttl为64时,意味着数据报应保留在本地区;当ttl的值为128时,意味着数据报应保留在本大洲;当ttl为255时,意味着数据报可发送到所有地方;默认情况下,该ttl的值为1。

2.3 一个简单的示例

接下来我们写一个小例子来看一下MulticastSocket的使用方式。这个程序将包含两个线程:1. 接收线程,主要用于接收信息;2. 主线程,主要用于发送信息。将这个程序部署到局域网上的几台电脑上,全部启动,就可以实现多台电脑的组播了,而且每台主机都可以发出信息,其它主机则会收到这条信息。

package com.heima.se.chat;
​
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Date;
import java.util.Scanner;
​
public class MulticastSocketDemo {public static void main(String[] args) throws IOException {//创建MuticastSocket对象,并监听端口55555MulticastSocket socket = new MulticastSocket(55555);//加入组:235.235.235.235socket.joinGroup(InetAddress.getByName("235.235.235.235"));
​//启动线程-此线程用于接收数据报new Thread(()->{byte[] bytes = new byte[1024];DatagramPacket packet = new DatagramPacket(bytes, bytes.length);while (true) {try {socket.receive(packet);System.out.println(new String(packet.getData(), 0, packet.getLength()));
​} catch (IOException e) {e.printStackTrace();}}}).start();
​//获取本机IPString localIp = InetAddress.getLocalHost().getHostAddress();
​//创建一个Scanner对象,用于接收控制台数据Scanner sc = new Scanner(System.in);while (true) {System.out.println("【请输入信息】");String msg = sc.next();// 获取当前时间格式化字符串,把IP、时间,以及要发送的文本连接在一起String time = String.format(" <====> %tF %<tT", new Date());msg = localIp + time + "n" + msg + "nn";//发送数据报socket.send(new DatagramPacket(msg.getBytes(),msg.getBytes().length,InetAddress.getByName("235.235.235.235"),55555));}}
}

通过上面的程序,我们发现,MulticastSocket类的使用和DatagramSocket类基本相同,只是多了一步加入组:joinGroup(),所有加入这个组的主机都将会收到信息。

三. 基于Swing和MulticastSocket实现的UDP群聊聊天室

接下来我们使用Swing为这个程序制作一个界面,让用户操作起来更加方便。

这个程序我们制作了两个类:

1). ChatFrame:这个类继承自JFrame,实现了界面的显示、布局等相关功能。

2). SocketChat:这个类继承自ChatFrame,加入了MulticastSocket的连接、信息发送和接收。

3.1 界面ChatFrame类

package com.heima.se.chat;
​
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();//让发送文本框得到焦点}
}

这个类中定义了很多抽象方法,这些抽象方法由子类实现。

3.2 组播聊天SocketChat类

package com.heima.se.chat;
​
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 + "nn";// 把文本转换成字节数组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 {// 创建数据包的字节数组,大小为1KBbyte[] 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);}
}

这个类使用MulticastSocket,使用端口:54321,组播地址:235.235.235.235。当用户在界面按下send按钮时,会触发sendText()方法发送数据;receive()方法用于使用线程接收数据,它是在父类的构造方法中被触发启动,启动后,使用无限循环进行信息的接收。

四.结束语

这篇文章我们使用MulticastSocket类实现了组播功能,并使用Swing和MulticastSocket制作了一个基于UDP的群聊聊天室,希望大家能够通过本篇文章了解MulticastSocket类的使用,有兴趣的朋友可以基于这个程序,为它添加更多的功能,例如:文件的发送、接收;表情图片的发送、接收等等。后面我还会为大家带来更多更实用的程序,期待大家来围观哦!谢谢大家!!

  


http://chatgpt.dhexx.cn/article/Y68iMU0y.shtml

相关文章

群聊私聊天建群社交即时通讯H5系统开发

群聊私聊天建群社交即时通讯H5系统开发 前端功能&#xff1a; 聊天、通讯录、动态、发现、我、多国语言、私聊、群聊、创建群聊&#xff08;设置免费、收费&#xff09;、发布动态、发信息&#xff08;图片、文字、红包、不支持语言&#xff09;、我的余额&#xff08;后台添加…

socket.io实现简易版群聊

最近学了点 websocket 的技术知识&#xff0c;了解到 node.js 有相关技术——socket.io可以实现&#xff0c;就想着实现一个简单版本的群聊。 先看看效果图 在浏览器中打开2个窗口&#xff0c;访问 http://localhost:3000/socket 目录结构 node 服务器代码实现 需要安装 exp…

Go实现简易聊天室(群聊)

参考&#xff1a;Go 群聊 ( goroutine ) 语雀 基于websocket的聊天室&#xff0c;可进一步参考&#xff1a; (1) go实现聊天室(WebSocket方式) (2) Golang代码搜集-基于websocketvue.js的简易聊天室 闲着无聊ing~ 一直想着能用go整一些好玩的小工具&#xff0c;想着想着突然想…

vue+websocket+nodejs创建聊天室- 创建群聊、加入群聊

前言 前几篇我们讲了如何创建聊天室,一对一/一对多聊天&#xff0c;以及加已读未读消息状态。 这篇主要讲如何创建群聊和加入群聊。 还是跟之前一样&#xff0c;本文只写新加入的逻辑&#xff0c;之前逻辑请查看之前文章。 PS&#xff1a;效果稍微有点粗糙哈哈&#xff0c;不要…

html群聊插件,团队群聊.html

&#xfeff;团队群聊 $axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; }; $axure.utils.getOtherPath function() { return resources/Other.html; }; $axure.utils.getReloadPath function() { return resources/reload.html;…

ajax聊天室创建群聊,js+node.js+socket.io实现聊天功能(私聊,创建群聊)

效果图: 这里启动了四个客户端进行测试 1. 登录,以及获取在线用户列表 2. 私聊功能 3. 群聊功能 偶然发现了WebSocket, 发现这个可以实时通信,在线聊天,所以就做了一个聊天工具的demo,记录一下 Socket.io WebSocket是js原生自带的,而Socket.io相当于是对WebSocket进行封装…

php怎么做群聊,workerman实现群聊

服务端&#xff1a; require_once "../vendor/autoload.php"; use Workerman\Worker; $worker new Worker(‘websocket://0.0.0.0:2345‘); $worker->count 1; $worker->onWorkerStart function($data){ echo "连接开始\n"; }; $worker->onCon…

致微信:我们什么时候重新定义群聊?

你永远都不知道&#xff0c;自己到底有多少微信群。 你也很难想象&#xff0c;一个20多人的小团队&#xff0c;相互之间会建几百个群&#xff0c;然后当你需要群发一个文件/通知时&#xff0c;还是找不到合适的群&#xff0c;怎么办&#xff1f;重新拉一个群呗。 如果你加的群稍…

怎么玩转LINE 群聊

关键词&#xff1a;LINE群聊 &#xff1b;SaleSmartly&#xff08;ss客服&#xff09; 一个 LINE 群聊是企业让客户了解其产品或服务的有效方式。如果使用得当&#xff0c; LINE 小组是企业同时快速培养与多个客户关系的绝佳场所。想了解更多吗&#xff1f;继续阅读&#xff0…

微信怎么找群聊?找回微信群聊只需要这样…

如今社会中的日常生活已经离不开微信&#xff0c;微信是社交界的一股清流&#xff0c;聊天、视频、语音等等功能&#xff0c;而且支付功能的用途范围在国内也甚是广泛。微信怎么找群聊&#xff1f;是的&#xff0c;当多个好友之间相互认识&#xff0c;或者都有一个共同点的时候…

免费tk域名+freewebhostingarea空间

1.申请免费域名 进入http://www.dot.tk&#xff08;推荐注册tk域名&#xff09;&#xff0c;申请一个新的域名&#xff0c;每次申请12个月以下是免费的&#xff0c;到期前14天可以免费续期 在此页面执行下一步之前&#xff0c;需要进行设置DNS服务器 2.获取DNS服务器 申请进…

免费国外PHP+MYSQL空间申请

这是一个在匈牙利的免费空间,但是在网页上方挂广告条(可以用CSS屏蔽掉). 支持的以下内容管理系统: - Joomla - Wordpress - e107 - Drupal - Simple Machine Forum (SMF) - PHP-Nuke - phpBB - Elxis - MyBB - CMS Made Simple 具体申请步骤: 1.进入www.freeweb.hu 2. 3. 4. 5.…

GIS地理空间数据免费获取

GIS地理空间数据免费获取 国内&#xff1a; 一、测绘地理信息局会提供权威的数据。 需要进入全国地理信息资源目录服务系统网站&#xff08;http://www.webmap.cn/main.do?methodindex&#xff09;&#xff0c;该网站提供&#xff1a;30米全球地表覆盖数据&#xff0c;Globe…

15 个国外免费卫星图像数据源介绍

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 数据源 (Data Source) 顾名…

新手建站十大免费空间推荐-稳定,可用的免费空间及其使用体验

新手建站十大免费空间推荐-稳定,可用的免费空间及其使用体验 新手建站十大 免费空间推荐-稳定,可用的 免费空间及其使用体验 一、OpenShift OpenShift 1、OpenShift空间是Red Hat的平台即服务的云计算平台(PaaS)&#xff0c;自成立以来就为大家提供 免费空间服务&#xff0c;深…

国外免费云存储 空间

苹果 微软 云存储 谷歌 亚马逊 Dropbox 摘要&#xff1a;为了能够让免费的云存储空间更大&#xff0c;我们就需要拥有更多的账户。现在有12种公共云存储的选择&#xff0c;最大可以得到112GB的免费存储空间&#xff0c;就让我们带着你慢慢分析他们的利弊。 如今市场上几乎所有提…

忍痛分享两个无限免费大空间不限速的外国云盘,中国境内可访问,附上网盘测评

之前分享了几个外国云盘&#xff0c;今天再来分享几个&#xff0c;顺便来个测评&#xff0c;对比一下看看哪个比较好 文章目录 网站介绍网站测评访问速度测试TusFiles 访问测速 ★★★HitFile 访问测速 ★★★★ 网盘上下载测速TusFiles 网络上下载速度&#xff08;无需注册&am…

申请国外免费空间必备的免费电话:短信、语音验证不再是难题

最近因为连续介绍了几个需要美国电话号码收取验证短信的免费空间和VPS,不少人还在为没有免费的可以用来接收短信、甚至是语音信息的网络电话在发愁着,在这里部落觉得很必要为大家列出几个可以免费使用的美国电话,以供大家不时之需。 像OVH那样的支持国内大陆手机号码接收验证…

分享一个用了很久的免费国外空间,适合用于测试

做开发的&#xff0c;尤其是WEB开发的&#xff0c;在开发期间习惯使用了本地服务器&#xff0c;配置不标准&#xff0c;环境和标准机房差的没远近。本人多次编好的程序&#xff0c;线下测试没什么问题&#xff0c;到放在线上后&#xff0c;各种的不兼容拍你一脸&#xff1b;用开…

国外免费高速php空间,0fees - 300M国外高速免费PHP空间

0fees是美国的免费空间&#xff0c;速度不错&#xff0c;提供300M空间&#xff0c;每月10G流量限制&#xff0c;ftp、web方式上传管理文件&#xff0c;支持PHP5&#xff0c;提供3个MySQL数据库&#xff0c;无限个支持POP3的电子邮箱&#xff0c;可以添加6个二级域名&#xff0c…