UDP协议程序设计

news2024/9/26 5:24:40

文章目录

  • 前言
  • 一、UDP程序设计是什么?
  • 二、使用步骤
    • 1.数据包套接字与多播套接字
    • 2.数据报包
    • 3.实操展示
  • 总结

前言

        UDP协议程序相对于TCP协议,就是一个广播喇叭给全村人听和两个人说悄悄话的差别。因此UDP的数据传输效率比TCP高,可以同时分享给所有在场的人。缺点就是不能保证数据能完整地传送到接收方那里,这个就像喇叭一样了,谁知道对方听没听,UDP只管广播。UPD和TCP协议都可以看作数据通讯协议。


一、UDP程序设计是什么?

        UDP程序设计是指使用用户数据报协议(UDP)进行网络通信的程序设计。

        UDP 是一种无连接的协议,它提供了一种简单的、不可靠的数据传输服务。与传输控制协议(TCP)相比,UDP 不提供可靠的数据传输和流控制机制,但具有较低的延迟和较小的数据传输量。

        UDP程序中,套接字负责接收或发送数据包,数据包负责保存数据内容,就像外卖小哥从一家店拿了外卖运送到各个门口一样,套接字是小哥,数据包是外卖。数据包套接字和多播套接字,两个套接字都是一回事,它们都是实现主机接收或发送数据包的类,只不过一个是父类一个是子类的关系。数

二、使用步骤

        UDP协议的使用如下:

        发送数据包

        (1)使用MulticastSocket()创建数据包套接字对象(记得绑定接口)。

        (2)将该数据包套接字使用joinGroup(InetAddress inet)方法加入指定的广播组地址(提前创建InetAddress对象,广播组地址范围:224.0.0.0~239.255.255.255)。

        (3)使用DatagramPacket()的构造方法创建要发送的数据包对象。

        (4)使用DatagramSocket()的send(DatagramPacket 数据包对象)方法发送数据包。

        接收数据包

        (1)使用MulticastSocket(int port)创建数据包套接字,绑定到指定端口。

        (2)将该数据包套接字使用joinGroup(InetAddress inet)方法加入指定广播方的广播组地址。

        (3)使用DatagramPacket(byte[] buf,int length)创建字节数组,接收数据包对象。

        (4)使用DatagramSocket类的receive(DatagramPacket 数据包对象)方法接收数据包。

1.数据包套接字与多播套接字

        (1)数据包套接字(DatagramSocket类)

        java.net包的DatagramSocket类用于创建可以发送和接收数据包的套接字。

        DatagramSocket类的构造方法:

new DatagramSocket();
//该构造方法创建DatagramSocket对象,创建数据包套接字。

new DatagramSocket(int port);
//该构造方法在创建数据包套接字对象的同时,并绑定了套接字的接口。

new DatagramSocket(int port,InetAddress address);
//该构造方法在创建数据包套接字对象的同时,并绑定了套接字的接口和指定的地址。

        创建好DatagramSocket对象,绑定了接口,再使用joinGroup()方法(已经使用过构造方法绑定地址的不用使用此方法),就可以发送和接收数据包了。 

DatagramSocket类的常用方法
方法功能描述返回值
send(DatagramPacket packet)发送指定的数据报到广播组void
receive(DatagramPacket packet)从广播组中接收数据报并将其存储在指定的数据包中void
 close()关闭DatagramSocket对象,关闭套接字void
setSoTimeout(int timeout)设置套接字的读取超时时间(以毫秒为单位)void
getLocalPort()返回此套接字绑定到的本地端口号int
connect(InetAddress address, int port)将此套接字连接到指定的远程地址和端口号void
disconnect()断开与远程地址的连接void
getInetAddress()返回与此套接字连接的远程主机的IP地址InetAddress
getPort()返回与此套接字连接的远程主机的端口号int
isClosed()检查套接字是否已关闭boolean
isConnected()检查套接字是否已连接到远程主机boolean

         DatagramSocket()类的receive()方法接收数据时,如果还没有可以接收的数据,正常情况下receive()方法将阻塞,一直等到网络上有数据传来,receive()方法接收到该数据并返回。如果receive()方法没有阻塞,肯定程序出了问题,多数情况下时因为使用了一个被其他程序占用的端口号。

        (2)多播套接字(MulticastSocket类)

MulticastSocket extends DatagramSocket

        MulticastSocket类是上面的DatagramSocket的子类,这意味着MulticastSocket类都能使用DatagramSocket类的常用方法了,由于该子类有更多的方法供使用,所以在实际编程中,用MuticastSocket创建套接字更多一些。

        MulticastSocket类的构造方法:

new MulticastSocket();
//创建一个未绑定到任何本地端口的MulticastSocket对象。

new MulticastSocket(int port);
//创建一个绑定到指定本地端口的MulticastSocket对象。

        什么情况下使用MulticastSocket类?

        (1)多播通信:应用程序需要向多个客户端发送数据,使用MulticastSocket更为合适。

        (2)简化的多播管理:MulticastSocket提供了方便的方法,如 joinGroup() 和 leaveGroup(),使得管理多播组变得简单。使用这些方法,你可以轻松地加入或离开多播组,而不需要手动处理组地址和端口。

        (3)自动处理:使用 MulticastSocket 时,系统会自动处理多播特性,例如适当的网络路由和数据包的复制,这样你就不需要担心底层的多播实现细节。

        (4)适用场景:在局域网内的实时数据传输(如视频流、在线游戏等),那么 MulticastSocket是更好的选择

MulticastSocket类的常用方法
方法功能描述返回值
joinGroup(InetAddress group)将套接字加入到指定的多播组,允许套接字开始接收或发送到该组的多播数据void
joinGroup(SocketAddress mcastaddr)通过指定的 SocketAddress 来加入多播组void
leaveGroup(InetAddress group)将套接字从指定的多播组中移除,停止接收或发送该组的多播数据void
leaveGroup(SocketAddress mcastaddr)通过指定的 SocketAddress 来离开多播组void
setTImeToLive(int tti)设置数据包的生存时间(TTL),用于控制多播数据包在网络中的跳数。TTL 的值通常在 1 到 255 之间void
getTimeToLive()获取当前设置的生存时间(TTL)值int
getLoopbackMode(boolean loopbackMode)设置是否允许将发送到多播组的数据包环回到本地的套接字void
getLoopbackMode()获取当前的环回模式设置boolean

        以上MulticastSocket类的常用方法,并没有写上继承自父类DatagramSocket类的方法,但该子类仍可以使用。子类的这些特有的常用方法使得MulticastSocket能够有效地管理多播组的加入和离开,以及控制多播数据的传输特性。

2.数据报包

        数据包(DatagramPackage类)

        java.net包的DatagramPacket类用于创建数据包对象,UDP程序中运输数据的包裹。

        DatagramPacket类的构造方法:

new DatagramPackage(byte[] buf,int length);
//该构造方法在创建数据包对象的同时,指定了数据包的数据内容和数据长度

new DatagramPackage(byte[] buf,int length, InetAddress address,int port);
//该构造方法在创建数据包对象的同时,指定了数据包的数据内容和数据长度,
//还有数据包发送的目标地址和端口

        创建数据包对象时,一般使用第二个构造方法,直接绑定UDP地址和端口,省事。 

DatagramPacket类的常用方法
方法功能描述返回值
getData()返回接收数据包的缓冲区byte[]
getLength()返回接收数据包的数据长度int
getAddress()返回发送数据包的目标地址InetAddress
getPort()返回发送数据包的目标端口int
setData(byte[] buf)设置发送数据包的缓冲区void
setLength(int length)设置发送数据包的数据长度void
setAddress(InetAddress address)设置接收数据包的目标地址void
setPort(int port)设置接收数据包的目标端口void

        以上方法都是用于调整和设置数据包的发送地址、接口,数据包的大小,字节长度等数据。 

3.实操展示

        项目设计:实时广播当地的天气,接收方可以为许多当地人的手机,必须实时且同步。

        广播组程序:使用MulticastSocket类创建多播套接字,构造方法中绑定接口和加入UDP地址;创建线程,使用Date类,格式化好后,打包到数据包对象中,套接字使用方法发送数据包到指定UDP地址处。

import java.io.IOException;
import java.lang.Thread;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.util.Date;
import java.text.SimpleDateFormat;
public class Sender extends Thread{
    int port = 9898;    //端口
    InetAddress group;  //广播组地址对象
    MulticastSocket socket; //多播数据包套接字
    
    @SuppressWarnings("deprecation")
    public Sender(){
        //广播组地址范围:224.0.0.0~239.255.255.255
        try{
            group = InetAddress.getByName("224.255.1.1");   //指定广播组地址
            socket = new MulticastSocket(port);    //套接字实例化并绑定接口
            socket.joinGroup(group);    //套接字加入UDP地址,可以向该地址接收或发送消息
        }catch(UnknownHostException e){
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    public void run(){
        while (true) {
            DatagramPacket packet;
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss");
            String message = "["+sf.format(date)+"] 天气预报:当前天气,多云。";
            byte data[] =message.getBytes();
            packet = new DatagramPacket(data, data.length, group,port); 
            //创建数据报,实例化,将上述数据存入数据包中,绑定了发送的UDP地址和接口
            try {
                socket.send(packet);    //向UDP地址发送该数据包
                System.out.println("Sending: " + message);
                Thread.sleep(1000);
            } catch (IOException e) {
                e.printStackTrace();
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Sender sender = new Sender();    //构造方法解决了套接字的问题,简化了代码
        sender.start();    //启动线程
    }

}

        客户端程序:接收类继承JFrame类,在构造方法中调用超类,创建窗口,实现界面交互(接收或中止接收广播消息),文本域中显示接收到的消息;实现Runnable接口,创建数据包对象,用套接字的方法和while循环不断接收指定UDP地址的广播消息;实现了ActionListener接口,为两个按钮添加监听事件和交互反馈,“接收消息”按钮被点击时,启动线程的start()方法,接收消息。

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

import javax.swing.*;
import java.lang.Runnable;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

@SuppressWarnings("deprecation")
public class Receiver extends JFrame implements Runnable,ActionListener{
    
    JButton ince = new JButton("接收消息");
    JButton stop = new JButton("停止接收");
    JTextArea inceAr = new JTextArea(10,10);
    JTextArea inced = new JTextArea(10, 10);
    Thread thread;
    boolean getMessage = true; //是否接收广播

    int port = 9898;
    InetAddress group;
    MulticastSocket socket;

    public Receiver(){
        super("广播数据报");    //引用超类构造方法,设置窗体标题
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);    //WindowConstants表示多个窗口的关闭方式
        inceAr.setForeground(Color.BLUE);
        
        JPanel north = new JPanel();
        north.add(ince);    //将按钮添加到面板north上
        north.add(stop);
        add(north,BorderLayout.NORTH);
        
        JPanel center = new JPanel();
        center.setLayout(new GridLayout(1,2));  //设置面板布局
        center.add(inceAr); //将文本域添加到面板上
        final JScrollPane scrollPane = new JScrollPane();
        center.add(scrollPane);
        scrollPane.setViewportView(inced);
        add(center, BorderLayout.CENTER);   //设置面板布局
        validate(); //重新验证容器中的组件,刷新组件
        setBounds(100, 50, 640, 380);
        setVisible(true);


        ince.addActionListener(this);
        stop.addActionListener(this);
    
        try{
            group = InetAddress.getByName("224.255.1.1");  //指定广播组地址
            socket = new MulticastSocket(port);     //实例化多播数据包套接字
            socket.joinGroup(group);
        } catch (IOException e){
            e.printStackTrace();
        }
        thread = new Thread(this);
    }

    

    @Override
    public void run(){
        while (getMessage) {
            byte data[] = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data, data.length, group,port);
            try {
                socket.receive(packet);
                String message = new String(packet.getData(),0,packet.getLength());
                inceAr.setText("正在接收的内容"+message);
                inced.append(message+"\n");
            } catch (IOException e) {
                e.printStackTrace();
            }
             
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource()==ince){
            ince.setBackground(Color.green);
            stop.setBackground(Color.red);
            if(!thread.isAlive()){
                thread = new Thread(this);
                getMessage = true;
            }
            thread.start();    
        }
        if(e.getSource()==stop){
            ince.setBackground(Color.red);
            stop.setBackground(Color.green);
            getMessage = false;
        }
    }

    public static void main(String[] args) {   
        new Receiver();
    }
}

        运行结果:

        广播组程序:

        

        如图所示,广播组程序向指定的UDP地址每隔一秒就发送一次天气播报。 

        客户端程序(当广播组程序启动后才能运行):

        

        如图所示,可以有多个客户端,同时且同步的获取到广播组广播的信息,只要它们连接的是同一个接口和UDP地址。


总结

        以上就是对UDP程序设计的简单介绍,本文简单介绍了如何搭建UDP程序,该程序在互联网通讯中的应用涉及面十分广泛。如果有疑问或指正的地方,欢迎读者在评论区中留言。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Windows PE》3.1 基本概念

在正式讲解PE文件格式之前,我们有必要先熟悉和PE相关的一些基本概念,以便于更好的理解和掌握PE文件格式。 本节必须掌握的知识点: 地址 指针 数据目录项 节 对齐方式 字符串编码格式 3.1.1 地址 ■在PE文件中涉及到四类地址 ●VA虚拟内存地…

【Linux】Shell 与权限:Linux 系统的双重保障

欢迎来到 CILMY23 的博客 🏆本篇主题为:Shell 与权限:Linux 系统的双重保障 🏆个人主页:CILMY23-CSDN博客 🏆系列专栏:Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法专题 …

三、搭建网站服务器超详细步骤——FinalShell下载安装使用流程(免费国产的SSH工具)+宝塔安装方法(分享两种安装宝塔的方法)

前言 本篇博客是搭建网站服务器模块下的第3部分 FinalShell下载安装使用流程 在分享这篇博客之前,首先讲一下,FinalShell软件是干什么用的,用大白话进行说明一下:这个软件是一款远程控制和管理服务器的软件,通过S…

C++字符串与整数的相互转换

文章目录 前言字符串转整数stoiisstringstreamatoi 字符转整数to_stringstringstreamsprintf ASCII码转换 前言 题目大致为: 给一组数据,去掉里面的2,然后再返回结果 例如: 输入:{20, 66, 521, 2024} 输出&#xff1…

手机如何切换网络IP地址:‌方法详解与操作指南‌

在当今的数字化时代,‌网络IP地址作为设备在网络中的唯一标识,‌扮演着至关重要的角色。‌对于手机用户而言,‌了解如何切换网络IP地址不仅有助于提升网络体验,‌还能在一定程度上保护个人隐私。‌本文将详细介绍手机切换网络IP地…

仿论坛项目--Kafka,构建TB级异步消息系统

阻塞队列 • BlockingQueue 解决线程通信的问题。阻塞方法:put、take。 • 生产者消费者模式生产者:产生数据的线程。消费者:使用数据的线程。 • 实现类ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueue、SynchronousQueue、D…

火语言RPA流程组件介绍--浏览器设置

🚩【组件功能】:浏览器设置,实例化对象,并执行是否显示图片/是否显示浏览器窗体等操作 配置预览 配置说明 操作浏览器类型 内置浏览器 外部浏览器 浏览器位置 本机安装的chrome浏览器可执行文件的路径(选择外部浏览器时必填)…

9月出海风向标:越南国庆节、巴西独立日、游戏外部开发大会、东京电玩节来袭!

9月如期而至,各位出海人准备好迎接新一轮增长机会了吗?以下是9月全球热门节日、行业大会活动信息: 01. 越南国庆节 越南国庆日,也称为“Quốc khnh nước CHXHCN Việt Nam”,是每年的9月2日,这一天标志着…

MySQL Workbench 的入门指南

前言 MySQL Workbench 是一个官方的图形化工具,用于开发、管理和设计 MySQL 数据库服务器。它提供了丰富的功能,可以帮助数据库管理员、开发者以及DBA们高效地工作。下面是一个MySQL Workbench的入门指南,介绍如何安装和使用它。 安装 MyS…

FP7209:非同步升压恒流LED区动IC

前言:LED驱动芯片是什么? LED驱动器(LED Driver),是指驱动LED发光或LED模块组件正常工作的电源调整电子器件。由于LED PN结的导通特性决定,它能适应的电源电压和电流变动范围十分狭窄,稍许偏离…

恋爱相亲交友系统源码原生源码可二次开发APP 小程序 H5,web全适配

直播互动:平台设有专门的直播间,允许房间主人与其他异性用户通过视频连线的方式进行一对一互动。语音视频交流:异性用户可以发起语音或视频通话,以增进了解和交流。群组聊天:用户能够创建群聊,邀请自己关注…

用亚马逊云科技Graviton高性能/低耗能处理器构建AI向量数据库(下篇)

简介: 今天小李哥将介绍亚马逊推出的云平台4代高性能计算处理器Gravition,并利用该处理器构建生成式AI向量数据库。利用向量数据库,我们可以开发和构建多样化的生成式AI应用,如RAG知识库,特定领域知识的聊天机器人等。…

Unity中使用四元数限制旋转

前言 在处理旋转相关的内容的时候,如果使用unity提供的欧拉角描述旋转,会出现一下两种问题 同一旋转的表示不唯一万向节死锁 绕轴90旋转与绕轴90+360旋转的表现是一致的 当某个特定轴达到某个特殊值时,绕一个轴旋转可能会覆盖另一…

Python 学习笔记(一)

input 函数 input():将输入数据的类型都转化为字符串 range 函数 自定义函数 函数与方法 列表 字符串 切片 集合 字典 函数的参数 匿名函数 文件操作 异常处理

JavaScript 21个常用数组使用方法

前言 在 JavaScript 中,数组是一种特殊类型的对象,用于存储和组织多个值。数组使您可以将值分组到单个变量名下,从而方便管理和操作数据集合。以下是更详细的解释: 在 JavaScript 中,一对方括号 [] 表示数组。数组中…

Kafka【第一篇】Kafka集群搭建

Kafka初识 1、Kafka使用背景 在我们大量使用分布式数据库、分布式计算集群的时候,是否会遇到这样的一些问题: 我们想分析下用户行为(pageviews),以便我们设计出更好的广告位我想对用户的搜索关键词进行统计&#xff…

Nexpose 6.6.268 发布下载,新增功能概览

Nexpose 6.6.268 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, release Sep 04, 2024 请访问原文链接:https://sysin.org/blog/nexpose-6/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.or…

JVM系列(五) -内存相关的调优参数

一、摘要 在上篇文章中,我们详细介绍了 JVM 的内存布局。 今天这篇文章,并结合之前的介绍知识,一起了解一下 JVM 内存相关的调优参数。 二、内存设置相关的命令 所有内存溢出的问题,除了代码可能存在问题以外,更直观的问题是内存空间不足,如何通过参数来控制各区域的…

【数据结构】排序算法篇二

【数据结构】排序算法篇二 1. 快速排序(hoare版本)(1)基本思想:(2)动态图解:(3)代码实现:(4)特性总结: 2. 快速…