JAVAEE值之网络原理(1)_传输控制协议(UDP)、概念、特点、结构、代码实例

前言

 在前两节中我们介绍了UDP数据报套接字编程,但是并没有对UDP进行详细介绍,本节中我们将会详细介绍传输层中的UDP协议。


一、什么是UDP?

 UDP工作在传输层,用于程序之间传输数据的。数据一般包含:文件类型,视频类型,jpg图片等。

1.1 基本概念:

UDP 的全称: 用户数据报协议(UDP,User Datagram Protocol),UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。如果程序员选择的是 UD, 而不是 TCP 的话,那么该应用程序相当于就是和 IP 直接打交道的。
 从应用程序传递过来的数据,会附加上多路复用/多路分解的源和目的端口号字段,以及其他字段,然后将形成的报文传递给下一层(网络层),网络层将传输层报文段封装到 IP 数据报中,然后尽力而为的交付给目标主机。最关键的一点就是,使用 UDP 协议在将数据报传递给目标主机时,发送方和接收方的传输层实体间是没有握手的。正因为如此,UDP 被称为是无连接的协议

1.2 UDP的特点

 UDP传输的过程类似于寄信。

无连接

 知道对端的IP和端口号就直接进行传输,不需要建立连接。

不可靠

 没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息;

面向数据报

 应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。比如:用UDP传输100个字节的数据:

如果发送端一次发送100个字节,那么接收端也必须一次接收100个字节;而不能循环接收10次, 每次接收10个字节。

缓冲区

UDP只有接收缓冲区,没有发送缓冲区:

  1. UDP没有真正意义上的 发送缓冲区。发送的数据会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
  2. UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致;如果缓冲区满了,再到达的UDP数据就会被丢弃;

大小受限

 UDP协议首部中有一个16位的最大长度。也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部)

二、UDP 报文结构

 如下图所示: UDP 的报文结构,每个 UDP 报文分为 UDP 报头和 UDP 数据区两部分。报头由 4 个 16 位长(2 字节)字段组成,分别说明该报文的源端口、目的端口、报文长度和校验值
在这里插入图片描述

16位源端口号(Source Port) :

 这个字段占据 UDP 报文头的前 16 位,通常包含发送数据报的应用程序所使用的 UDP 端口。接收端的应用程序利用这个字段的值作为发送响应的目的地址。这个字段是可选项,有时不会设置源端口号。没有源端口号就默认为 0 ,通常用于不需要返回消息的通信中。

16位目标端口号(Destination Port)

表示接收端端口,字段长为 16 位。

长度

 该字段占据 16 位,表示 UDP 数据报长度,包含 UDP 报文头和 UDP 数据长度。因为 UDP 报文头长度是 8 个字节,所以这个值最小为 8,最大长度为 65535 字节。

16位校验和(Checksum)

 UDP 使用校验和来保证数据安全性,UDP 的校验和也提供了差错检测功能,差错检测用于校验报文段从源到目标主机的过程中,数据的完整性是否发生了改变。常见的检验方法:循环冗余检测(CRC)。

  • 为什么 UDP 会提供差错检测的功能?
     这其实是一种 端到端 的设计原则,这个原则说的是要让传输中各种错误发生的概率降低到一个可以接受的水平。
  • 如何基于校验和来完成数据校验呢?
  1. 发送方,把要发送的数据整理好(称为 data1),通过一定的算法,计算出校验和 checksum1
  2. 发送方把 data1 和 checksum1 一起通过网络发送出去.
  3. 接收方收到数据, 收到的数据称为 data2(数据可能和 data1 就不一样了),收到数据cHecksum1
  4. 接收方再根据 data2 重新计算校验和 (按照相同的算法),得到 checksum2
  5. 对比 checksum1 和 checksum2 是否相同,如果不同, 则认为 data2 和 data1 一定不相同.如果checksum1 和 checksum2 相同,则认为 data1 和 data2 大概率是相同的(理论上存在不同的可能性,概率比较低,工程上忽略不计)

三、通过代码理解UDP的特点

3.1 无连接

UDP协议本身不会储存对端的信息,要在发送数据的时候,才会显示指定要传输给谁?

 DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
 				requestPacket.getSocketAddress()); 
 			// 构造这个数据报,需要指定数据内容,也指定下一个数据报要发给谁
 socket.send(responsePacket);

3.2 不可靠

3.3 面向数据报

 DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
 				requestPacket.getSocketAddress()); 
 			// 构造这个数据报,需要指定数据内容,也指定下一个数据报要发给谁
 socket.send(responsePacket);

3.4 全双工

 通过一个socket,既可以send,也可以receive.

	socket.send(requestPacket);
  // 3.尝试服务器返回的响应了
   DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
   socket.receive(responsePacket);

上一节中的参考代码(https://blog.csdn.net/2301_80653026/article/details/139443856):

UDP客户端

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.channels.DatagramChannel;

/**
 * @author Zhang
 * @date 2024/5/2015:38
 * @Description:
 */
public class UdpEchoServer {

    //创建一个datagramSocket对象,这是后续操作网卡的基础
    private DatagramSocket socket = null;

    public UdpEchoServer(int port) throws SocketException {
        //此写法是手动指定端口
        socket = new DatagramSocket(port);

        // 此写法是让服务器自动分配端口
       // socket = new DatagramSocket();

    }

    //通过这个方法来启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动");

        while(true){
            // 1. 读取请求并解析
            /**
             *  DatagramPacket这个队形来承载从网卡这边读取的数据,
             *  收到的数据需要一个内存空间来保存这个数据
             *  DatagramPacket 内部不能自动分配空间,需要程序员手动创建,交给DatagramPacket进行处理
             */
            DatagramPacket requestPacket  = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);   //当服务器一旦启动,就会立即执行receive方法,入伏哦客户端请求还没到,receive就会阻塞到客户端请求到达
            // 当完成receive后,数据以二进制的形式存储到DatagramPacket
            // 要想把这里的数据显示出来,好需要把这个二进制转变成字符串
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());

            // 2.根据请求计算响应(一般服务器都会经理的过程)
            // 由于此处是回显服务器,请求是啥样,响应就是啥样
            String response = process(request);

            // 3. 把响应写会到客户端
            //      写一个响应对象,DatagramPacket
            //      往DatagramPacket 构造刚才数据,并通过 sent 返回

            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());
            // 构造这个数据报,需要指定数据内容,也指定下一个数据报要发给谁
            socket.send(responsePacket);

            // 4.打印一个日志,把这次数据交互的详情打印出来
            System.out.printf("[%s:%d] req = %s, resp = %s\n",requestPacket.getAddress().toString(),
                    requestPacket.getPort(),request,response);
        }
    }

    public String process(String request){
        return request;
    }
    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}
服务端

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
 * @author Zhang
 * @date 2024/5/2015:38
 * @Description:
 */
public class UdpEchoClient {

    private DatagramSocket socket = null;
    private  String serverIP = "";
    private  int serverPort = 0;

    public  UdpEchoClient(String ip,int port) throws SocketException {
        // 创建这个对象,不能手动指定端口
      socket = new DatagramSocket();
      //由于UDP自身不会持有对端的信息,就需要在应用程序里,吧对端的情况给记录下来
        serverIP = ip;
        serverPort = port;
    }

    public void start() throws IOException {
        System.out.println("客户端启动!");
        Scanner scanner = new Scanner(System.in);
        while (true){
            // 1.从控制台读取数据,作为请求
            System.out.print("->");
            String request = scanner.next();
            // 2. 把请求内容构造成 DatagramPacket 对象,发送给服务器
            DatagramPacket  requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
                    InetAddress.getByName(serverIP), serverPort);
            socket.send(requestPacket);

            // 3.尝试服务器返回的响应了
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);
            // 4.把响应转换成字符串,并先显示出来
            String response =  new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);
        client.start();
    }
}

总结

UDP特点:无连接、不可靠、面向数据报、全双工。

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

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

相关文章

掌握Google搜索结果获取

在数据驱动的决策世界中,获取准确而全面的信息至关重要。Google 搜索结果抓取是一种强大的技术,可以让企业、调查人员和研究人员从搜索引擎结果中提取可靠的数据。本综合指南将深入研究 Google 搜索结果的最佳实践、工具和道德考量,以确定能够…

攻防演练之-网络安全产品大巡礼二

书接上文,《网络安全攻防演练风云》专栏之攻防演练之-网络安全产品大巡礼一,这里。 “咱们中场休息一会,我去接杯水哈”,看着认真听讲的众人,王工很是满意,经常夹在甲乙两方受气的他,这次终于表…

流批一体计算引擎-9-[Flink]中的数量窗与时间窗

1 数量窗 1.1 数量滚动窗口 0基础学习PyFlink——个数滚动窗口(Tumbling Count Windows) 1.1.1 代码分析 Tumbling Count Windows是指按元素个数计数的滚动窗口。 滚动窗口是指没有元素重叠的窗口。 (1)构造了一个KeyedStream,用于存储word_count_data中的数据。…

2025年QS世界大学排名,美国大学表现如何?

大多数访问学者申请,在探讨QS大学排名中美国大学的表现时,我们不难发现这些学府在全球高等教育舞台上占据着举足轻重的地位。QS排名作为评估全球大学综合实力的重要指标之一,充分展示了美国大学在学术声誉、科研实力、教学质量和国际影响力等…

专属部署的优势和企业价值

纷享销客支持多种部署方式,满足不同企业在高性能、隔离性、安全性、合规性等方面的要求。 公有云SaaS 公有云SaaS服务即直接使用纷享云服务,CRM应用、数据等均在纷享云,客户只需开通账号和相关服务,做到了即开即用。 纷享云采用…

Error:Kotlin: Module was compiled with an incompatible version of Kotlin.

一、问题:运行spring boot项目时,idea报出错误:时提示报错如下图: 错误代码: Error:Kotlin: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.6.0, expected …

springboot p2p金融信贷平台的设计与实现-计算机毕业设计源码82978

摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对p2p金融信贷平台等问题,对p2p金…

PDF编辑与修正 提高工作效率 Enfocus PitStop Pro 2022 中文

Enfocus PitStop Pro 2022是一款专为Mac用户设计的强大PDF编辑和校对工具。它支持添加、删除、合并、分割PDF页面,以及文本和图像的编辑,如文字替换、字体更改、颜色调整等。内置自动修复功能,能快速检测并修复缺失字体、重叠文本等常见问题。…

健身小程序:智能化助力个人健身旅程

一、智能化功能的核心 健身小程序的智能化功能主要体现在以下几个方面: 智能健身计划推荐:小程序内置了先进的算法,能够根据用户的身体状况、健身目标和时间安排,智能推荐个性化的健身计划。这些计划不仅科学合理,而且…

在Vue2和Vue3中ECharts如何使用,详细步骤,ref,$ref。echarts官网。

不管是在vue2中还是在vue3中其实本质上的原理和步骤都是一样的,只是语法可能有所不同。 为了方便大家看起乱,vue2和vue3我分开写。 echarts官网: https://echarts.apache.org/zh/index.html Vue2篇: 1.导入echarts包&#xf…

云联HIS系统源码,二级医院信息系统源码,支持云架构部署模式

采用java语言开发B/S广域互联模式,支持云架构部署模式,支持大数据分析技术;支持与医保平台接口、电子票据对接。 云HIS系统相关技术: 后台:JavaSpring,SpringBoot,SpringMVC,Sprin…

数学模型:操作系统中FCFS、SJF、HRRN算法的平均周转时间比较 c语言

摘 要 研究目的:比较操作系统中进程调度FCFS、SJF、HRRN算法的平均周转时间和带权周转时间的大小关系。 研究方法:在建模分析时,分别举4个进程的例子,1个进程用两个字母分别表示到达时间和执行时间。分两种极端情况&#xff0c…

解锁工业数据流:NeuronEX 规则调试功能实操指南

工业企业要实现数据驱动的新质生产力升级,一个重要的环节便是如何准确、可靠地收集并利用生产过程中的数据流。 NeuronEX 工业边缘软件中的规则调试功能,可帮助用户在安全的环境中模拟数据输入,测试和优化数据处理规则,从而提前发…

低代码是什么,低代码平台可以解决哪些业务问题

低代码(Low-Code)是一种软件开发方法,它使得开发人员能够通过图形界面、拖放组件和模型驱动的逻辑,快速地构建和部署应用程序,而无需编写大量的代码。 近年来,低代码正在逐步帮助企业解决业务问题&#xff…

STL——Stacks容器

一、stack 1.操作 语法: <><>!所有的这些操作可以被用于堆栈. 相等指堆栈有相同的元素并有着相同的顺序。 2.empty 语法: bool empty();如当前堆栈为空&#xff0c;empty() 函数 返回 true 否则返回false. 3.pop 语法: void pop();pop() 函数移除堆栈中最顶层元…

React 懒加载源码实现

懒加载 React 中懒加载是一种按需加载组件的机制&#xff0c;有些组件不需要在页面初始化就进行加载&#xff0c;这些组件可以按需加载&#xff0c;当需要时再进行加载。懒加载是怎么实现的呢&#xff1f;如果要实现一个懒加载功能应该怎么去做呢&#xff1f;可以通过异步动态…

专业学习|博弈论-课程改革

学习来源&#xff1a;北京大学刘霖《博弈论》MOOC公开课 备注&#xff1a;仅做学习分享&#xff0c;请勿转载&#xff0c;转载必究&#xff01; &#xff08;一&#xff09;博弈论的预备知识 基本的微积分的知识和概率论的知识。简单的说会求导数&#xff0c;会求简单的积分&am…

BUUCTF---web---[SUCTF 2019]CheckIn

1、点击题目连接来到页面 2、上传正常的jpg文件&#xff0c;提示内容不能有<?。本来打算上传图片马&#xff0c;但是有过滤 3、可以改成下面的图片马&#xff1a; <script languagephp>eval($_POST[cmd]);</script> 4、将上面的一句话木马先写成txt再修改后缀为…

01_基于人脸的常见表情识别实战_深度学习基础知识

1. 感知机 感知机通常情况下指单层的人工神经网络,其结构与 MP 模型类似(按照生物神经元的结构和工作原理造出来的一个抽象和简化了模型,也称为神经网络的一个处理单元) 假设由一个 n 维的单层感知机,则: x 1 x_1 x1​ 至 x n x_n xn​ 为 n 维输入向量的各个分量w 1 j…

【C语言】一篇带你高强度解析精通 字符串函数和内存函数 (万字总结大全,含思维导图)(建议收藏!!!)

【 库函数】——字符串函数和内存函数 目录 思维导图&#xff1a; 一&#xff1a;字符串函数 1.1&#xff1a;字符串常规函数 1.1.1&#xff1a;长度不受限制的字符串函数 1.1.1.1&#xff1a;strlen函数 1.1.1.2&#xff1a;strcpy函数 1.1.1.3&#xff1a;strcat函数 …