白话初识UDP协议

news2024/9/25 21:20:12

UDP是什么

UDP是一个传输层的数据包装协议,特点有:

  1. 无连接(不需要两端连通就可以发送消息给接收端)
  2. 不可靠传输(无法知道数据是否送达)
  3. 面向数据报(以数据报为数据传输单位)
  4. 全双工(两端都可发送可接收)
  5. 发送数据的大小受限(64KB的缓冲区)

先简单了解一下UDP协议的格式:

协议报头组成大概就是:

源端口号 + 目的端口号 + UDP的长度 + UDP校验和

每一项都是用16bits(2字节)来存储,总共报头大小为64bits也就是8字节。

因为有了16bits的UDP长度限制,所以就是限制了数据的内容不能超过16bits,即64KB的大小,假如有更大的数据就只能拆成多个数据报来传输,这个过程可能会出现数据丢失等问题。所以发送数据的大小受限是UDP协议的一个缺点。

如何使用UDP协议进行传输

使用UDP传输的基本操作有:

  1. 传输通过DatagramSocket在两个进程之间通讯,数据通过DatagramPacket打包。
  2. DatagramSocket的参数通常为Port
  3. DatagramPacket的参数通常为byte[]和byte[]的长度(将字节数组打包到packet中)
  4. 主机地址由IP决定,进程由端口号(PORT)决定
  5. 接收端只需要绑定固定的端口号,发送端需要知道接收端的端口号和IP(主机的保留域名为localhost,或者127.0.0.1)
  6. 创建Socket地址通过InetSocketAddress API,

如何编写最简单的UDP代码

有了上述基本操作我们可以写出对最基本的UDP客户端服务器:

对服务器有:

public class UdpEchoServer {

    private static final int PORT = 8888;
    public static void main(String[] args) throws IOException {
        //创建一个DatagramSocket数据报套接字,用于在进程间通讯
        DatagramSocket socket = new DatagramSocket(PORT);

        while (true) {
            //创建bytes[]来获取数据socket中的内容
            //创建DatagramPacket来打包数据(对服务器而言是获取DatagramSocket中的数据)
            byte[] bytes = new byte[516];
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
            
            //阻塞等待数据报接收
            System.out.println("等待接收UDP数据报...");
            socket.receive(packet);
            //这里执行完后其实已经完成了接收工作

            //可以调用一些方法来查看获取的数据、数据来源等
            System.out.println("客户端IP:" + packet.getSocketAddress());
            System.out.println("客户端Port:" + packet.getPort());
            System.out.println("客户端发送的原数据:" + packet.getData());
        }
    }
}

对客户端有:

public class UdpClient {
    private static final SocketAddress address =
        new InetSocketAddress("127.0.0.1", 8888);

    public static void main(String[] args) throws IOException {
        //创建DatagramPacket用于打包数据
        DatagramSocket socket = new DatagramSocket();
        byte[] bytes = "miss everyday".getBytes();
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address);
        socket.send(packet);
        System.out.println("客户端数据已发送...");
    }
}

注:对服务器而言,传入PORT就是告诉Socket从这个端口接收数据。对客户端而言,不需要告诉Socket从哪里接收数据,但是需要告诉Socket把数据送去哪个端口,所以把SocketAddress给写入了packet中,由packet去告诉Socket往哪个端口送数据。

知道了如何写出基本的UDP协议下的数据传输后,我们可以稍微升级一下,写一个翻译服务器,即在客户端发送翻译请求,然后服务器返回发送的结果。

对服务器有:

public class UdpDictClient {

    private static final SocketAddress address =
            new InetSocketAddress("localhost", 4090);

    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        Scanner scanner = new Scanner(System.in);
        while (true) {
            byte[] resp = new byte[128];
            DatagramPacket packet = new DatagramPacket(resp, resp.length);

            System.out.print("请输入要翻译的英文(以.结尾):");
            byte[] req = scanner.next().getBytes();
            DatagramPacket request = new DatagramPacket(req, req.length, address);
            socket.send(request);
            System.out.println("翻译请求已发送...");

            socket.receive(packet);
            String answer = new String(packet.getData());

            System.out.println("结果:" + answer);
        }
    }
}

对客户端有:

public class UdpDictServer {

    private static HashMap<String, String> dict;
    private static final int PORT = 4090;

    public static void main(String[] args) throws IOException {
        iniDict();
        System.out.println("服务器启动...");
        DatagramSocket socket = new DatagramSocket(PORT);
        while (true) {
            System.out.println("正在等待接收客户端请求...");
            byte[] req = new byte[128];
            DatagramPacket request = new DatagramPacket(req, req.length);
            socket.receive(request);
            
            System.out.println("已收到客户端" + 
                request.getSocketAddress() + "请求,开始处理...");
            String getBytes = new String(request.getData());
            char[] chars = getBytes.toCharArray();
            StringBuilder stringBuilder = new StringBuilder();
            for (char aChar : chars) {
                if (aChar == '.') {
                    break;
                } else {
                    stringBuilder.append(aChar);
                }
            }
            getBytes = stringBuilder.toString();

            String resp = dict.getOrDefault(getBytes, "没有找到翻译");
            byte[] bytes = resp.getBytes();
            DatagramPacket response =
                    new DatagramPacket(bytes, bytes.length, request.getSocketAddress());
            socket.send(response);
            System.out.println("已向客户端返回响应...");
            System.out.println("------------------");
        }
    }

    private static void iniDict () {
        dict = new HashMap<>();
        dict.put("Matty", "Lyh");
        dict.put("Justin", "比伯");
        dict.put("Stephen", "库里");
    }
}

这样下来应该就对UDP有一定认识了

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

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

相关文章

vue项目cli2 升级 cli3

vue-cli2 升级 vue-cli3 由于vue-cli2 版本太低&#xff0c;升级到vue-cli3 采用的方法是新建cli3项目&#xff0c;对比差异&#xff0c;在cli2项目单独升级 检查环境 node环境检查版本是否在8.11版本以上 npm uninstall vue-cli -g 卸载旧版本的vue-cli npm install -g vue/…

广州蓝景分享—VSCode 前端开发必备插件推荐

Hello~~各位小伙伴好&#xff0c;今天广州蓝景整理一波前端开发必备插件&#xff0c;绝对可以提高你的生产力&#xff0c;希望这篇文章对大家有所帮助。 开发综合推荐 别名路径跳转 插件名&#xff1a;别名路径跳转 使用说明: 别名路径跳转插件&#xff0c;支持任何项目&…

BrightlyPro - 照片视屏后期自动调色增亮工具

BrightlyPro - 照片视屏后期自动调色增亮工具 BrightlyPro 自动增强您的照片和视频&#xff0c;你最需要它。通过一个滑块&#xff0c;BrightlyPro 立即使您的照片自适应地亮起来&#xff0c;同时保持光影之间令人愉悦的平衡&#xff0c;而不会扭曲已经点亮的区域。 下载 ➤ …

day07 面向对象

1. 类和对象 **面向对象和面向过程的思想对比 : ** ​ **面向过程 &#xff1a;**是一种以过程为中心的编程思想&#xff0c;实现功能的每一步&#xff0c;都是自己实现的 ​ **面向对象 &#xff1a;**是一种以对象为中心的编程思想&#xff0c;通过指挥对象实现具体的功能…

Java开发学习(三十四)----Maven私服(二)本地仓库访问私服配置与私服资源上传下载

一、本地仓库访问私服配置 我们通过IDEA将开发的模块上传到私服&#xff0c;中间是要经过本地Maven的 本地Maven需要知道私服的访问地址以及私服访问的用户名和密码 私服中的仓库很多&#xff0c;Maven最终要把资源上传到哪个仓库? Maven下载的时候&#xff0c;又需要携带用…

Nginx限制每秒请求次数,限制每秒连接次数,下载速度限制

Hi I’m Shendi 为了防止网站被恶意攻击&#xff0c;总是需要做一些防护措施 最外层的web服务器是Nginx&#xff0c;于是寻找 nginx 的一些关于防护措施的配置&#xff0c;记录在此 https://sdpro.top/blog/html/article/1005.html 一些变量 首先列举出会使用到的一些变量 …

XXEXML漏洞详解

XXE&XML漏洞详解1.XML基础1.1.XML基础介绍1.2.XML文档结构1.3.DTD介绍1.4.实体类介绍1.5.外部实体2.XXE漏洞基本介绍2.1.XXE漏洞基本概念2.2.XXE漏洞危害2.3.XXE漏洞输出形式2.4.XXE漏洞相关差异3.XXE漏洞测试3.1.有回显测试3.1.1.有回显案例3.1.1.1.测试回显位置3.1.1.2.构…

【XR】Oculus揭秘Touch控制器追踪技术:LED 匹配

Oculus揭秘Touch控制器追踪技术&#xff1a;LED 匹配 稳健的状态机&#xff0c;它允许我们能够在各种求解器之间进行转换 &#xff08;映维网 2019年11月05日&#xff09;映维网曾在九月分享了一篇关于Oculus Constellation追踪系统&#xff0c;其中负责AR/VR设备输入追踪的F…

动态规划——区间dp

区间dp 文章目录区间dp概述模板例题石子合并思路代码环形石子合并思路代码能量项链思路代码加分二叉树思路代码凸多边形的划分思路代码棋盘分割思路代码总结概述 区间dp就是在区间上进行动态规划&#xff0c;求解一段区间上的最优解。主要是通过合并小区间的最优解进而得出整个…

Infragistics Ignite UI for Web

Infragistics Ignite UI for Web 添加了新的透视网格组件&#xff0c;它在透视表中显示数据&#xff0c;并帮助对数据集执行复杂的分析。 使用透视网格以多维透视表结构配置和显示数据。 行和列表示不同的数据组&#xff0c;数据单元值表示聚合。 这允许基于简单的平面数据集进…

Sql Server 中FOR XML PATH(‘‘)函数用法

1. 如下表 2. 转换xml -- 将查询结果转换成xml形式 select name from zz FOR XML PATH(root);结果 说明 FOR XML PATH(‘root’)中root是xml根节点&#xff0c;所以在结果集中每条数据根节点为root&#xff0c;上面的sql将多行数据合并为一行&#xff0c;并且使用属性名name…

黑马Hive+Spark离线数仓工业项目--数仓事实层DWB层构建(3)

网点物料事实指标分析及实现 目标&#xff1a;实现DWB层网点物料事实指标表的构建 路径 - step1&#xff1a;目标需求 - step2&#xff1a;数据来源 - step3&#xff1a;目标实现 实施 - **目标需求**&#xff1a;基于物料申请单的信息统计物料申请数量、物料申请金额等…

Scriptcase配置日期字段位置日期格式的功能

Scriptcase配置日期字段位置日期格式的功能 在“翻译应用程序”工具中添加了搜索索引的快速搜索。 在项目列表屏幕上添加了垂直方向的固定条。 在登录和许可证注册屏幕上添加了显示/隐藏密码图标。 在快速编辑中添加了错误位置选项。 在Express Edit中的模式中添加了“显示字段…

电容触摸屏GT9147介绍

GT9147简介 GT9147是采用最新的电容检测技术&#xff0c;内置高性能微信号检测电路&#xff0c;可很好地解决LCD干扰和共模干扰问题。软件算法方面&#xff0c;专门基于单层互容的电气环境所设计&#xff0c;可支持5点触控。同时支持HotKnot功能 GT9147可同时识别5个触摸点位的…

宝塔面板安装使用教程

宝塔面板使用教程 宝塔面板是一款服务器管理软件&#xff0c;可以帮助用户建立网站&#xff0c;一键配置服务器环境&#xff0c;使得用户通过web界面就可以轻松的管理安装所用的服务器软件。 1 宝塔面板安装 1.1 宝塔面板的安装 宝塔面板官网地址&#xff1a;https://www.bt.…

线程相关学习记录(2)

锁分类 按照对共享资源是否上锁&#xff0c;可以分为&#xff1a; 乐观锁悲观锁 乐观锁的定义&#xff1a; 乐观锁是一种乐观思想&#xff0c;认为自己在使用数据时不会有别的线程修改数据&#xff0c;所以不会添加锁&#xff0c;只是在提交修改的时候去判断一下&#xff0c…

【通过点按其他按钮修改按钮的位置 Objective-C语言】

一、继续我们上一个例子 1.下面我们要实现的功能,是通过点按4个方向键,修改最上面那个图片按钮的位置 2.首先,我们把4个方向按钮实现一下 我先拽1个按钮上去,注意,我们不是1上来就拽6个按钮, 而是先拽1个按钮上去 我设置这1个按钮,大家看一下,这个按钮上有文字吗,…

盒子模型中box-sizing: border-box;的作用

我们都知道 盒子模型 它都是由 外边距(margin) 边框(border) 内边距(padding) 内容(content)组成的。 如果我们按照下面的设置&#xff0c;得到的是一个300*300大小的红色正方形 .box {height: 300px;width: 300px;background-color: red; } <body><div class&q…

如何使用阻塞队列BlockingQueue

文章目录什么是阻塞队列阻塞队列的特点BlockingQueue不是新的东西学会使用队列阻塞队列四组APISynchronousQueue 同步队列什么是阻塞队列 阻塞队列本质上还是一种队列&#xff0c;遵循先进先出&#xff0c;后进后出的原则&#xff0c;在此基础上&#xff0c;如果出队时阻塞队列…

BM32 合并二叉树

题目 已知两颗二叉树&#xff0c;将它们合并成一颗二叉树。合并规则是&#xff1a;都存在的结点&#xff0c;就将结点值加起来&#xff0c;否则空的位置就由另一个树的结点来代替。例如&#xff1a; 两颗二叉树是: Tree 1 Tree 2 合并后的树为 数据范围&#xff1a;树上节点数…