UDP概念特点+编程流程

news2025/5/25 22:50:19

UDP概念+编程流程

目录

一、UDP基本概念

1.1 概念

1.2 特点

1.2.1 无连接性:

1.2.2 不可靠性

1.2.3 面向报文

二、UDP编程流程

2.1 客户端 cli.c

2.2 服务端ser.c


一、UDP基本概念

1.1 概念

UDP 即用户数据报协议(User Datagram Protocol ) ,是 OSI 参考模型中一种无连接的传输层协议,提供的是无连接,不可靠,数据报服务。

1.2 特点

1.2.1 无连接性:

UDP 传输数据之前源端和终端不建立连接,发送方直接将数据打包成 UDP 数据报发送到网络上,无需等待接收方确认,减少了开销和发送数据前的时延 。比如在线游戏中,玩家操作指令频繁发送,使用 UDP 可快速将指令发出,无需建立连接等待 。

1.2.2 不可靠性

UDP 不保证数据的可靠传输,不提供报文到达确认、排序及流量控制等功能 ,也没有数据包重传机制和错误恢复机制 。若传输中数据包丢失、损坏或乱序,UDP 不会自动处理 。像网络视频会议,偶尔丢包对整体影响不大,更看重实时性,就适合用 UDP 。

1.2.3 面向报文

UDP 对应用程序交下来的报文,在添加首部后就向下交付给 IP 层,既不拆分也不合并,保留报文边界 。这要求应用程序选择合适报文大小 。

二、UDP编程流程

2.1 客户端 cli.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main()
{
    // 创建一个 UDP 套接字,AF_INET 表示使用 IPv4 地址族,SOCK_DGRAM 表示使用 UDP 协议
    int sockfd = socket(AF_INET,SOCK_DGRAM,0); 
    // 检查套接字是否创建成功,如果创建失败(返回值为 -1),则终止程序
    if( sockfd == -1 ) 
    {
        exit(1);
    }

    // 定义一个 IPv4 套接字地址结构体,用于存储服务器地址信息
    struct sockaddr_in saddr; 
    // 将服务器地址结构体 saddr 的内存空间清零
    memset(&saddr,0,sizeof(saddr)); 
    // 设置地址族为 IPv4
    saddr.sin_family = AF_INET; 
    // 将端口号 6000 从主机字节序转换为网络字节序
    saddr.sin_port = htons(6000); 
    // 将 IP 地址 "127.0.0.1" 从点分十进制字符串转换为网络字节序的二进制数
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 

    // 进入无限循环,用于持续进行数据的发送和接收操作
    while( 1 ) 
    {
        // 提示用户输入信息
        printf("input:\n"); 
        // 定义一个字符数组,用于存储用户输入的数据,大小为 128 字节
        char buff[128] = {0}; 
        // 从标准输入(键盘)读取一行数据到 buff 数组中,最多读取 128 个字符
        fgets(buff,128,stdin); 
        // 检查用户输入的内容是否以 "end" 开头,如果是则跳出循环
        if( strncmp(buff,"end",3) == 0) 
        {
            break;
        }

        // 向服务器地址发送数据,strlen(buff) - 1 是去掉 fgets 读取时包含的换行符
        sendto(sockfd,buff,strlen(buff)-1,0,(struct sockaddr*)&saddr,sizeof(saddr)); 
        // 将字符数组 buff 的内容清零,为下次接收数据做准备
        memset(buff,0,128); 
        // 初始化地址结构体长度变量,用于存储从服务器接收数据时地址结构体的长度
        int len = sizeof(saddr); 
        // 从服务器接收数据,存储到 buff 数组中
        recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len); 
        // 打印接收到的数据
        printf("buff=%s\n",buff); 
    }

    // 关闭套接字,释放相关资源
    close(sockfd); 
    // 正常终止程序
    exit(0); 
}

sendto(sockfd,buff,strlen(buff)-1,0,(struct sockaddr*)&saddr,sizeof(saddr));

  • 函数作用sendto 是用于在 UDP 套接字上发送数据的函数。它可以将数据发送到指定的目标地址。
  • 参数解释
    • sockfd:之前创建好的 UDP 套接字描述符,通过它来确定使用哪个套接字发送数据。
    • buff:这是一个字符数组,存储着要发送的数据内容,也就是用户通过 fgets 从标准输入获取并准备发送给服务器的数据。
    • strlen(buff) - 1strlen 函数用于获取 buff 中字符串的长度。因为 fgets 函数读取输入时会把换行符 \n 也读取到 buff 数组中,而实际发送数据时通常不需要这个换行符,所以减去 1 来去掉它 。这个值表示实际要发送的数据长度。
    • 0:表示发送数据时的标志位,这里设置为 0 表示没有特殊的发送选项。
    • (struct sockaddr*)&saddr:将服务器地址结构体 saddr 的指针强制转换为通用的 sockaddr 指针类型,用于指定数据要发送到的目标地址,这里就是服务器的地址。
    • sizeof(saddr):表示目标地址结构体 saddr 的大小,用于告诉 sendto 函数地址信息占用的字节数。

recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);

  • 函数作用recvfrom 是用于在 UDP 套接字上接收数据的函数,同时它还能获取发送方的地址信息。
  • 参数解释
    • sockfd:UDP 套接字描述符,通过它确定从哪个套接字接收数据。
    • buff:用于存储接收到的数据的字符数组,这里它的大小为 128 ,但实际接收数据时预留 1 个字节用于存储字符串结束符 \0 ,所以指定接收长度为 127 。
    • 0:接收数据时的标志位,设置为 0 表示没有特殊接收选项。
    • (struct sockaddr*)&saddr:用于存储发送方(客户端)地址信息的结构体指针,将其强制转换为通用的 sockaddr 指针类型。在函数执行过程中,它会被填充为实际发送数据的客户端的地址信息。
    • &len:是一个指向表示地址结构体长度变量的指针。recvfrom 函数会根据实际接收到的地址信息长度来更新这个变量的值。

2.2 服务端ser.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>

int main()
{
    // 创建一个 UDP 套接字,AF_INET 表示使用 IPv4 地址族,SOCK_DGRAM 表示 UDP 协议
    int sockfd = socket(AF_INET,SOCK_DGRAM,0); 
    // 检查套接字是否创建成功,若失败(返回 -1)则退出程序
    if( -1 == sockfd)
    {
        exit(1);
    }

    // 定义两个 IPv4 套接字地址结构体,saddr 用于服务器地址,caddr 用于客户端地址
    struct sockaddr_in saddr, caddr;
    // 将服务器地址结构体 saddr 的内存初始化为 0
    memset(&saddr,0,sizeof(saddr));
    // 设置地址族为 IPv4
    saddr.sin_family = AF_INET;
    // 将端口号 6000 从主机字节序转换为网络字节序
    saddr.sin_port = htons(6000);
    // 将 IP 地址 "127.0.0.1" 从点分十进制转换为网络字节序
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // 将套接字 sockfd 绑定到指定的地址(saddr)
    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    // 检查绑定操作是否成功,若失败(返回 -1)则打印错误信息
    if( res == -1)
    {
        printf("bind err\n");
    }

    // 进入无限循环,持续接收和响应客户端消息
    while( 1 )
    {
        // 定义字符数组 buff,用于存储接收到的消息,初始化为 0
        char buff[128] = {0};
        // 初始化客户端地址结构体 caddr 的长度
        int len = sizeof(caddr);
        
        // 从客户端接收数据,存储到 buff 中,同时获取客户端地址信息
        int n = recvfrom(sockfd,buff,128,0,(struct sockaddr*)&caddr,&len);
        // 打印接收到的消息内容
        printf("buff=%s\n",buff);
        // 向客户端发送 "ok" 消息
        sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
    }

    // 关闭套接字,释放资源
    close(sockfd);
    // 正常退出程序
    exit(0);
}

int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr)); 

这行代码的作用是将之前创建的套接字 sockfd 绑定到由 saddr 结构体所表示的网络地址上,并通过返回值 res 来判断绑定操作是否成功。 

bind 函数是用于在网络编程中把一个套接字(socket)和一个特定的地址绑定在一起的系统函数。在 TCP 或 UDP 服务器程序中,通常使用 bind 函数将服务器套接字绑定到一个指定的 IP 地址和端口号上,这样服务器就能在该地址上监听并接收来自客户端的连接请求或数据。

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

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

相关文章

Flutter项目之设置页

目录&#xff1a; 1、实现效果图2、实现流程2.1、引入依赖2.2、封装弹窗工具类2.3、设置页2.4、路由中注册设置页面 1、实现效果图 2、实现流程 2.1、引入依赖 2.2、封装弹窗工具类 import package:fluttertoast/fluttertoast.dart;class CommontToast {static showToast(Str…

通过GO后端项目实践理解DDD架构

最近在工作过程中重构的项目要求使用DDD架构&#xff0c;在网上查询资料发现教程五花八门&#xff0c;并且大部分内容都是长篇的概念讲解&#xff0c;晦涩难懂&#xff0c;笔者看了一些github上入门的使用DDD的GO项目&#xff0c;并结合自己开发中的经验&#xff0c;谈谈自己对…

天线静电防护:NRESDTLC5V0D8B

一. 物联网天线的使用环境 1.1 联网天线广泛应用于智能家居领域&#xff0c;比如智能门锁、智能摄像头等设备中&#xff0c;通过天线实现设备与家庭网络的连接&#xff0c;用户可以远程控制和监控家居设备。以智能摄像头为例&#xff0c;它通过天线将拍摄的画面实时传输到用户…

【Linux 并发与竞争】

【Linux 并发与竞争】 Linux是一个多任务操作系统&#xff0c;肯定会存在多个任务共同操作同一段内存或者设备的情况&#xff0c;多个任务甚至中断都能访问的资源叫做共享资源&#xff0c;就和共享单车一样。在驱动开发中要注意对共享资源的保护&#xff0c;也就是要处理对共享…

实用类题目

1. 密码强度检测 题目描述&#xff1a;生活中&#xff0c;为保证账户安全&#xff0c;密码需要有一定强度。编写一个方法&#xff0c;接收一个字符串作为密码&#xff0c;判断其是否符合以下强度要求&#xff1a;长度至少为 8 位&#xff0c;包含至少一个大写字母、一个小写字…

STM32F103C8T6-基于FreeRTOS系统实现步进电机控制

引言 上一篇文章讲述了如何使用蓝牙连接stm32进行数据收发控制步进电机&#xff0c;这篇在之前的基础上通过移植操作系统&#xff08;FreeRTOS或者其他的也可以&#xff0c;原理操作都类似&#xff09;实现步进电机控制。 上篇博客指路&#xff1a;STM32蓝牙连接Android实现云…

macOS安装java

一、下载 官网Java Downloads | Oracle 安装载java8,下载对应的JDK Java Downloads | Oracle 二、双击安装 安装 完成 三、查看安装位置 打开终端窗口&#xff0c;执行命令&#xff1a; /usr/libexec/java_home -V /Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Content…

zkmall模块商城:B2C 场景下 Vue3 前端性能优化的广度探索与实践

ZKmall作为面向B2C场景的模块化电商平台&#xff0c;其前端性能优化在Vue3框架下的实践融合了架构设计、渲染机制与业务特性&#xff0c;形成了一套多维度的优化体系。以下从技术实现与业务适配两个维度展开分析&#xff1a; 一、Vue3响应式系统深度适配 ​Proxy驱动的精准更新…

【Netty篇】Future Promise 详解

目录 一、 Netty Future 与 Promise —— 异步世界的“信使”与“传话筒”&#x1f680;1、 理解 Netty Future2、 理解 Netty Promise 二、 代码案例解读&#x1f4bb;例1&#xff1a;同步处理任务成功&#x1f44d;例2&#xff1a;异步处理任务成功&#x1f4f2;例3&#xff…

视频分析设备平台EasyCVR安防视频管理系统,打造电石生产智能视频监控新体系

一、背景介绍 电石生产中的出炉工序是整个生产流程中最为繁重且危险的环节。在开堵炉眼的过程中&#xff0c;电石极易发生飞溅现象&#xff0c;尤其在进行吹氧操作时&#xff0c;人员灼伤的风险极高。鉴于此&#xff0c;该工序正逐步由传统的人工操作模式向智能化方向转变。然…

从 PyTorch 到 ONNX:深度学习模型导出全解析

在模型训练完毕后&#xff0c;我们通常希望将其部署到推理平台中&#xff0c;比如 TensorRT、ONNX Runtime 或移动端框架。而 ONNX&#xff08;Open Neural Network Exchange&#xff09;正是 PyTorch 与这些平台之间的桥梁。 本文将以一个图像去噪模型 SimpleDenoiser 为例&a…

Android 应用添加Tile到SystemUI QuickSettings

安卓源码里有谷歌给的关于 Tile 的说明。 frameworks/base/packages/SystemUI/docs/qs-tiles.md SystemUI QuickSettings 简称QS&#xff0c;指的是 下拉菜单里的区域。区域里的一个选项就是一个 Tile 。 下图是 frameworks/base/packages/SystemUI/docs/ 里的附图示例&#…

【MySQL】前缀索引、索引下推、访问方法,自适应哈希索引

最左前缀原则 对于INDEX(name, age)来说最左前缀可以是联合索引的最左N个字段, 也可以是字符串索引的最左M个字符。 SELECT * FROM t WHERE name LIKE 张%其效果和单独创建一个INDEX(name)的效果是一样的若通过调整索引字段的顺序, 可以少维护一个索引树, 那么这个顺序就是需要…

Android Studio开发知识:从基础到进阶

引言 Android开发作为移动应用开发的主流方向之一&#xff0c;曾吸引了无数开发者投身其中。然而&#xff0c;随着市场饱和和技术迭代&#xff0c;当前的Android开发就业形势并不乐观&#xff0c;竞争日益激烈。尽管如此&#xff0c;掌握扎实的开发技能仍然是脱颖而出的关键。本…

ocr-身份证正反面识别

在阿里云官网&#xff0c;申请一个token [阿里官方]身份证OCR文字识别_API专区_云市场-阿里云 (aliyun.com) 观察一下post请求body部分json字符串&#xff0c;我们根据这个创建一个java对象 先默认是人像面 public class IdentityBody {public String image;class configure…

单节锂电池4.2V升压5V都有哪些国产芯片推荐?国产SL4011高效,高性价比

针对单节锂电池&#xff08;4.2V&#xff09;升压至5V应用中 SL4011升压芯片 的核心优势解析&#xff0c;结合其技术参数与典型应用场景进行详细说明&#xff1a; 1. 宽输入电压与高兼容性 输入范围&#xff1a;2.7V-12V&#xff0c;完美覆盖单节锂电池全周期电压&#xff08;3…

机器学习 | 神经网络介绍 | 概念向

文章目录 &#x1f4da;从生物神经元到人工神经元&#x1f4da;神经网络初识&#x1f407;激活函数——让神经元“动起来”&#x1f407;权重与偏置——调整信息的重要性&#x1f407;训练神经网络——学习的过程&#x1f407;过拟合与正则化——避免“死记硬背” &#x1f440…

视频孪生重构施工逻辑:智慧工地的数字化升级

当"智慧工地"概念在2017年首次写入《建筑业发展"十三五"规划》时&#xff0c;行业普遍将其等同于摄像头与传感器的简单叠加。十年数字浪潮冲刷下&#xff0c;智慧工地的内涵已发生本质跃迁&#xff1a;从工具层面的信息化改造&#xff0c;进化为基于视频数…

六根觉性:穿透表象的清净觉知之光

在喧嚣的禅堂里&#xff0c;老禅师轻叩茶盏&#xff0c;清脆的声响划破沉寂。这声"叮"不仅震动耳膜&#xff0c;更叩击着修行者的心性——这正是佛教揭示的六根觉性在世间万相中的妙用。当我们凝视《楞严经》中二十五圆通法门&#xff0c;六根觉性犹如六道澄明之光&a…

spring:注解@Component、@Controller、@Service、@Reponsitory

背景 spring框架的一个核心功能是IOC&#xff0c;就是将Bean初始化加载到容器中&#xff0c;Bean是如何加载到容器的&#xff0c;可以使用spring注解方式或者spring XML配置方式。 spring注解方式直接对项目中的类进行注解&#xff0c;减少了配置文件内容&#xff0c;更加便于…