UDP简单总结

UDP:用户数据报协议

  • 特点: 无连接、不可靠通信

  • 不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口、目的地IP、程序端口和数据(限制在64KB内)

  • 发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,故不可靠

  • Java代码常用方法
    • DatagramSocket():创建一个未绑定到任何本地地址和端口的DatagramSocket对象。
      DatagramSocket socket = new DatagramSocket();
      
    • DatagramSocket(int port):创建一个绑定到指定端口的DatagramSocket对象。
      DatagramSocket socket = new DatagramSocket(8080);
      
    • send(DatagramPacket packet):发送数据报包。
      byte[] data = "Hello, world!".getBytes();
      DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("localhost"), 8080);
      socket.send(packet);
      
    • receive(DatagramPacket packet):接收数据报包。
      byte[] buffer = new byte[1024];
      DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
      socket.receive(packet);
      
    • setSoTimeout(int timeout):设置接收超时时间(以毫秒为单位)。
      socket.setSoTimeout(5000); // 设置5秒超时
    • close():关闭套接字。
      socket.close();
      
    • bind(SocketAddress bindaddr):将套接字绑定到特定的本地地址和端口。
      socket.bind(new InetSocketAddress("localhost", 8080));
    • getLocalSocketAddress():获取套接字绑定的本地地址和端口。
      SocketAddress localAddress = socket.getLocalSocketAddress();
      

 下面是一个简单的示例代码,演示如何使用DatagramSocket发送和接收UDP数据报:

import java.net.*;

public class UDPSocketExample {
    public static void main(String[] args) {
        try {
            // 创建一个DatagramSocket对象并绑定到本地端口8080
            DatagramSocket socket = new DatagramSocket(8080);

            // 准备发送的消息字符串
            String message = "Hello, UDP!";
            
            // 将消息字符串转换为字节数组
            byte[] sendData = message.getBytes();
            
            // 获取接收者的地址(本地主机)和端口号(8081)
            InetAddress receiverAddress = InetAddress.getByName("localhost");
            int receiverPort = 8081;

            // 创建一个DatagramPacket对象,用于发送数据
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, receiverAddress, receiverPort);
            
            // 发送数据报包
            socket.send(sendPacket);
            System.out.println("Sent message: " + message);

            // 创建一个字节数组用于接收数据
            byte[] receiveData = new byte[1024];
            
            // 创建一个DatagramPacket对象,用于接收数据
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            
            // 接收数据报包
            socket.receive(receivePacket);
            
            // 从接收的数据报包中获取消息字符串
            String receivedMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("Received message: " + receivedMessage);

            // 关闭套接字
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

        在此示例中,我们使用DatagramSocket实现了一个简单的UDP通信程序。首先,我们创建了一个DatagramSocket对象并绑定到本地端口8080。然后,我们准备了要发送的消息字符串,并将其转换为字节数组。接着,我们获取了接收者的地址(本地主机)和端口号(8081),并创建了一个DatagramPacket对象用于发送数据。我们发送了数据报包,并在控制台打印了发送的消息。接着,我们创建了一个用于接收数据的字节数组和DatagramPacket对象,并接收了从本地端口8081发送的数据报包。最后,我们从接收的数据报包中获取消息字符串,并在控制台打印接收到的消息。最后,我们关闭了套接字。

        当然这只是实现了单发单收,我们可以利用死循环实现一个客户端和一个服务端的多发多收。下面我们利用线程实现多发多收。

下面是一个示例代码,演示如何实现多发多收的UDP通信:

import java.net.*;

public class MultiSendReceiveUDP {
    public static void main(String[] args) {
        try {
            // 创建DatagramSocket对象并绑定到本地端口8080
            DatagramSocket socket = new DatagramSocket(8080);

            // 启动接收线程
            Thread receiverThread = new Thread(new Receiver(socket));
            receiverThread.start();

            // 创建发送者线程并启动
            Thread sender1 = new Thread(new Sender(socket, "Message 1", "localhost", 8081));
            Thread sender2 = new Thread(new Sender(socket, "Message 2", "localhost", 8081));
            sender1.start();
            sender2.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 接收者线程类
    static class Receiver implements Runnable {
        private DatagramSocket socket;

        public Receiver(DatagramSocket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                // 创建一个字节数组用于接收数据
                byte[] receiveData = new byte[1024];

                while (true) {
                    // 创建一个DatagramPacket对象,用于接收数据
                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    
                    // 接收数据报包
                    socket.receive(receivePacket);

                    // 从接收的数据报包中获取消息字符串
                    String receivedMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
                    System.out.println("Received message: " + receivedMessage);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 发送者线程类
    static class Sender implements Runnable {
        private DatagramSocket socket;
        private String message;
        private String receiverHost;
        private int receiverPort;

        public Sender(DatagramSocket socket, String message, String receiverHost, int receiverPort) {
            this.socket = socket;
            this.message = message;
            this.receiverHost = receiverHost;
            this.receiverPort = receiverPort;
        }

        @Override
        public void run() {
            try {
                // 将消息字符串转换为字节数组
                byte[] sendData = message.getBytes();
                
                // 获取接收者的地址和端口号
                InetAddress receiverAddress = InetAddress.getByName(receiverHost);

                // 创建一个DatagramPacket对象,用于发送数据
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, receiverAddress, receiverPort);
                
                // 发送数据报包
                socket.send(sendPacket);
                System.out.println("Sent message: " + message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

        在此示例中,我们创建了一个MultiSendReceiveUDP类,其中包含了main方法,以及ReceiverSender类,分别用于接收和发送数据。在main方法中,我们创建了一个DatagramSocket对象并绑定到本地端口8080,并启动了一个接收者线程。然后,我们创建了两个发送者线程,并将它们分别启动。每个发送者线程将向本地主机的端口8081发送一条消息。接收者线程将一直接收来自发送者的消息,并在控制台打印出来。

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

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

相关文章

备考分享丨云计算HCIE实验考试需要注意什么

去年九月底我在朋友的推荐下报考了誉天的云计算方向,在此期间我非常感谢田sir、苗苗老师和凡凡老师,每次我遇见问题找他们都能给我完完全全的解决,给我这个非科班出身的学员很大的鼓励与帮助。 我是经济学专业,毕业之后没有考研&…

java数据结构与算法刷题-----LeetCode785. 判断二分图

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 文章目录 深度优先广度优先 二分图:将所有结点分成两个集合&am…

​如何使用 ArcGIS Pro 制作带贴图建筑

对于用GIS软件制作三维建筑,很多时候都是制作的建筑体块,这里为大家介绍一下怎么使用 ArcGIS Pro 制作带贴图的建筑,希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的建筑数据,除了建筑数据,常见…

Simple_SSTI_2

Simple_SSTI_2 破解思路 1、启动场景2、用kali的tplmap扫一下 1、启动场景 http://114.67.175.224:18040/ 然后机会发现 页面啥也不是,查看源码后,看了好像又没看 2、用kali的tplmap扫一下 安装tplmap【已安装,可略过】:在kali终端安装git…

GitHub 仓库 (repository) Branch - SSH clone URL - Clone in Desktop - Download ZIP

GitHub 仓库 [repository] Branch - SSH clone URL - Clone in Desktop - Download ZIP 1. Branch2. SSH clone URL3. Clone in Desktop4. Download ZIPReferences 1. Branch 显示当前分支的名称。从这里可以切换仓库内分支,查看其他分支的文件。 2. SSH clo…

A Learning-Based Approach for IP Geolocation

下载地址:Towards IP geolocation using delay and topology measurements | Proceedings of the 6th ACM SIGCOMM conference on Internet measurement 被引次数:185 Abstract 定位IP主机地理位置的能力对于在线广告和网络攻击诊断等应用程序是非常吸引力的。虽然先前的方…

CSS-浮动文字环绕布局、隐藏属性display、overflow、三角形制作、鼠标样式

文字环绕布局 CSS文字环绕布局是指在网页中让文字环绕在图片或其他元素周围的布局方式。这通常通过CSS中的float属性来实现。你可以将图片设置为float: left;或float: right;,然后在文本元素中使用clear属性来清除浮动,以确保文字不会覆盖图片。另外&am…

React路由快速入门:Class组件和函数式组件的使用

1. 介绍 在开始学习React路由之前,先了解一下什么是React路由。React Router是一个为React应用程序提供声明式路由的库。它可以帮助您在应用程序中管理不同的URL,并在这些URL上呈现相应的组件。 2. 安装 要在React应用程序中使用React路由,…

使用pytorch构建控制生成GAN(Controllable GAN)网络模型

本文为此系列的第四篇Controllable GAN,上一篇为Conditional GAN。文中使用训练好的模型和优化噪声向量来操纵生成图像的特定属性,若有不懂的无监督知识点可以看本系列第一篇。 原理 本文主要讲什么是控制生成,以及如何做到控制生成。 什么是…

设计模式学习笔记 - 设计模式与范式 -行为型:7.责任链模式(下):框架中常用的过滤器、拦截器是如何实现的?

概述 上篇文章《6.责任链模式(上):原理与实现》,学习了职责链模式的原理与实现,并且通过一个敏感词过滤框架的例子,展示了职责链模式的设计意图。本质上来说,它跟大部分设计模式一样&#xff0…

Lvs+keepalived+nginx搭建高可用负载均衡集群,爱了爱了

检查 最后启动nginx服务 135配置虚拟网卡 检查 最后启动nginx服务 Nginx.conf配置如下 关闭132的keepalived服务后 浏览器能正常访问 132在keepalived配置中加入脚本 脚本内容 132清除ipvsadm中的规则,vip不见 133收到vip 自我介绍一下,小编13年上海交大毕业&…

React ant 点击导航条闪烁

问题 : 点击当前位置会出现闪一下的效果 另一种点击方式 , 不会闪 原因 : 没有传递具体的参数给点击事件 , 导致在函数内部无法准确判断要展示哪个子菜单,可能导致页面状态的短暂变化,出现闪烁效果 代码 : // 左侧子菜单弹出const showSonMenu routeK…

【前端】学习路线

1、基础 1.1 HTML 菜鸟教程-主页:https://www.runoob.com/ 可以学习:HTML、CSS、Bootstrap等 1.2 CSS 《通用 CSS 笔记、建议与指导》 1.3 JavaScript 1)入门:JavaScript 的基本语法 2)进阶:现代 …

hive管理之ctl方式

hive管理之ctl方式 hivehive --service clictl命令行的命令 #清屏 Ctrl L #或者 ! clear #查看数据仓库中的表 show tabls; #查看数据仓库中的内置函数 show functions;#查看表的结构 desc表名 #查看hdfs上的文件 dfs -ls 目录 #执行操作系统的命令 !命令…

JVM—垃圾收集器

JVM—垃圾收集器 什么是垃圾 没有被引用的对象就是垃圾。 怎么找到垃圾 引用计数法 当对象引用消失,对象就称为垃圾。 对象消失一个引用,计数减去一,当引用都消失了,计数就会变为0.此时这个对象就会变成垃圾。 在堆内存中主…

SRNIC、选择性重传、伸缩性、连接扩展性、RoCEv2优化(六)

参考论文SRDMA(A Scalable Architecture for RDMA NICs ):https://download.csdn.net/download/zz2633105/89101822 借此,对论文内容总结、加以思考和额外猜想,如有侵权,请联系删除。 如有描述不当之处&…

【MATLAB高级编程】第二篇 | 元胞数组(cell)操作

【第二篇】元胞数组(cell)操作 1. 创建元胞数组cell2. 查看和修改cell内的元素值3. 高级操作: 可视化作图显示cell内的内容4. 把矩阵转换成单元数组5. 把单元数组转换成结构体变量 你好! 欢迎进入 《MATLAB高级编程》 文章系列 ,每…

物理服务器与云服务器的租用对比

​ 物理服务器:每个基于 Web 的应用程序都依赖于一个服务器,该服务器提供网络中的数据存储,并可根据请求提供给客户端。例如,用户使用浏览器访问 Web 应用程序。服务器可确保托管客户端可以使用该硬件组件。与其他托管可能性相比&…

云平台和云原生

目录 1.0 云平台 1.1.0 私有云、公有云、混合云 1.1.1 私有云 1.1.2 公有云 1.1.3 混合云 1.2 常见云管理平台 1.3 云管理的好处 1.3.1 多云的统一管理 1.3.2 跨云资源调度和编排需要 1.3.3 实现多云治理 1.3.4 多云的统一监控和运维 1.3.5 统一成本分析和优化 1.…

基于Lipschitz李式指数的随机信号特征识别和故障检测matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 Lipschitz李式指数定义与性质 4.2 Lipschitz李式指数的估计 4.3 Lipschitz李式指数在信号特征识别与故障检测中的应用 5.完整程序 1.程序功能描述 基于Lipschitz李式指数的随机信号特…