【网络编程】如何将UDP协议变得更可靠

news2024/12/24 7:38:10
  • (꒪ꇴ꒪ ),Hello我是祐言QAQ
  • 我的博客主页:C/C++语言,数据结构,Linux基础,ARM开发板,网络编程等领域UP🌍
  • 快上🚘,一起学习,让我们成为一个强大的攻城狮!
  • 送给自己和读者的一句鸡汤🤔:集中起来的意志可以击穿顽石!
  • 作者水平很有限,如果发现错误,请在评论区指正,感谢🙏

ps:首先解释一下为什么没更新了,并不是我不学习了,而是招聘会和面试让我很难有时间坐下来打字,后续还是会更新的。


        近日面试中遇到一个问题,面试官问到UDP时问我如何使UDP变得更可靠,我只知道UDP也可以重传,但是具体如何实现呢未曾接触,于是今天分享一下。

        想必大家和我一样也背过UDP协议的内容,它是一种面向无连接的协议,它在网络通信中提供了高性能的数据传输,但不保证数据的可靠性。尽管UDP在某些情况下非常有用,但在需要可靠性的场景中,我们可以采用一些策略来增加UDP传输的可靠性。本文将介绍这些策略,包括超时重传、有序接收、应答确认和滑动窗口流量控制。

一、UDP概述

        UDP是一种简单的面向数据包的协议,它不提供连接管理、流控制或拥塞控制,因此通常被用于实时通信和多媒体流。但由于UDP不保证数据包的可靠性,它可能在不可靠网络环境下导致数据包丢失或乱序。

二、增加UDP可靠性的策略

1. 超时重传(定时器)

        超时重传是一种基本的机制,它通过设置定时器来确保数据包在有限时间内到达接收方。如果定时器超时并且没有接收到应答,发送方将重新发送数据包。

        下面是一个简单的C++代码示例:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[1024];

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("创建套接字出错");
        exit(1);
    }

    // 服务器地址配置
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    socklen_t server_len = sizeof(server_addr);

    while (true) {
        // 发送数据
        const char* data = "Hello, UDP!";
        sendto(sockfd, data, strlen(data), 0, (struct sockaddr*)&server_addr, server_len);

        // 设置超时
        struct timeval timeout;
        timeout.tv_sec = 2;
        timeout.tv_usec = 0;
        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));

        // 接收响应
        int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, &server_len);
        if (n < 0) {
            std::cout << "超时,重新发送数据..." << std::endl;
        } else {
            buffer[n] = '\0';
            std::cout << "从服务器接收响应:" << buffer << std::endl;
        }

        sleep(1);  // 在发送下一个数据包之前等待
    }

    return 0;
}

2. 有序接收(添加包序号)

        为了解决UDP数据包的乱序问题,我们可以为每个数据包添加一个包序号,并在接收端按照序号对数据包进行排序。这有助于确保数据包以正确的顺序到达接收方。

        以下是一个示例C++代码:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[1024];
    int expected_seq = 0;

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("创建套接字出错");
        exit(1);
    }

    // 服务器地址配置
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    socklen_t server_len = sizeof(server_addr);

    while (true) {
        int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, &server_len);
        buffer[n] = '\0';
        int seq;
        memcpy(&seq, buffer, sizeof(int));

        if (seq == expected_seq) {
            // 接收到期望的数据包
            std::cout << "从服务器接收数据:" << (buffer + sizeof(int)) << std::endl;
            expected_seq++;
        }

        // 发送应答
        sendto(sockfd, &seq, sizeof(int), 0, (struct sockaddr*)&server_addr, server_len);
    }

    return 0;
}

3. 应答确认(Seq/Ack应答机制)

        Seq/Ack应答机制允许接收方向发送方发送应答,以确认已成功接收到数据包。如果发送方未收到应答,它可以选择重传数据包。

        以下是一个示例C++代码:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet_in.h>

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[1024];
    int ack = 0;

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("创建套接字出错");
        exit(1);
    }

    // 服务器地址配置
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    socklen_t server_len = sizeof(server_addr);

    while (true) {
        int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, &server_len);
        buffer[n] = '\0';
        int seq;
        memcpy(&seq, buffer, sizeof(int));

        if (seq == ack) {
            // 接收到期望的数据包
            std::cout << "从服务器接收数据:" << (buffer + sizeof(int)) << std::endl;
            ack++;
        }

        // 发送应答
        sendto(sockfd, &ack, sizeof(int), 0, (struct sockaddr*)&server_addr, server_len);
    }

    return 0;
}

4. 滑动窗口流量控制等机制(滑动窗口协议)

        滑动窗口协议允许发送方和接收方之间协商,以控制数据包的流量和顺序。这有助于优化传输的效率和可靠性。

        以下是一个示例C++代码:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[1024];
    int ack = 0;
    int window_size = 5;
    int recv_buffer[window_size];

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("创建套接字出错");
        exit(1);
    }

    // 服务器地址配置
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    socklen_t server_len = sizeof(server_addr);

    while (true) {
        int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, &server_len);
        buffer[n] = '\0';
        int seq;
        memcpy(&seq, buffer, sizeof(int));

        if (seq == ack) {
            // 接收到期望的数据包
            std::cout << "从服务器接收数据:" << (buffer + sizeof(int)) << std::endl;
            ack++;

            // 检查后续数据包
            for (int i = 0; i < window_size; i++) {
                int next_seq = ack + i;
                if (recv_buffer[next_seq] != 0) {
                    std::cout << "从服务器接收数据:" << recv_buffer[next_seq] << std::endl;
                    recv_buffer[next_seq] = 0;
                }
            }
        } else {
            // 存储未按顺序到达的数据包
            recv_buffer[seq] = (buffer + sizeof(int));
        }

        // 发送应答
        sendto(sockfd, &ack, sizeof(int), 0, (struct sockaddr*)&server_addr, server_len);
    }

    return 0;
}

三、总结

        尽管UDP是一种不提供可靠性传输的协议,但通过实现超时重传、有序接收、应答确认和滑动窗口流量控制等机制,我们可以增加UDP传输的可靠性。这些策略可以根据具体应用的需求来选择和组合,以满足不同的可靠性要求。然而,需要注意的是,这些机制在应用层实现,会引入额外的复杂性和开销,因此对于某些需要高度可靠性的应用,TCP可能仍然是更好的选择

        更多C/C++语言Linux系统数据结构ARM板实战相关文章,关注专栏:

   手撕C语言

            玩转linux

                    脚踢数据结构

                            系统、网络编程

                                     探索C++

                                             6818(ARM)开发板实战

📢写在最后

  • 今天的分享就到这啦~
  • 觉得博主写的还不错的烦劳 一键三连喔~
  • 🎉🎉🎉感谢关注🎉🎉🎉

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

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

相关文章

Verilog刷题[hdlbits] :Always case

题目&#xff1a;Always case Case statements in Verilog are nearly equivalent to a sequence of if-elseif-else that compares one expression to a list of others. Its syntax and functionality differs from the switch statement in C. Verilog中的Case语句几乎等同…

答题小程序排位pk答题怎么玩

答题小程序排位PK答题升级赛是一个备受喜爱的功能&#xff0c;它不仅增加了用户之间的互动和竞争&#xff0c;同时也为答题小程序增添了更多的趣味性和挑战性。那么&#xff0c;如何参与答题小程序的排位PK答题升级赛呢&#xff1f;本文将详细介绍答题小程序的排位PK答题升级赛…

网络安全与TikTok:年轻一代的数字素养

在数字时代&#xff0c;互联网成为我们生活的重要组成部分&#xff0c;而社交媒体平台则在年轻一代中变得日益流行。其中&#xff0c;TikTok作为一个短视频分享平台&#xff0c;吸引了全球数以亿计的用户&#xff0c;尤其年轻人。 然而&#xff0c;与其快速的普及相伴随的是网…

思维模型 首因效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。先入为主&#xff0c;一见钟情。 1 首因效应的应用 1.1 面试中的首因效应 小李是一名应届毕业生&#xff0c;他准备参加一家知名互联网公司的面试。在面试前&#xff0c;他做了充分的准备…

leetcode 215. 数组中的第K个最大元素

2023.11.7 本题两个思路&#xff0c;一个是先将数组排序&#xff0c;再从后往前数第k个元素即为第k个最大的元素。 或者使用优先队列&#xff0c;将数组元素放入队列中&#xff0c;当队列元素数量超过k时&#xff0c;弹出队列元素&#xff0c;由于优先队列的性质&#xff0c;每…

CodeWhisperer 的正确使用

1、重点&#xff1a; 重点1&#xff1a; 推出 Amazon Bedrock。这项新服务允许用户通过 API 访问来自 AI21 Labs、Anthropic、Stability AI 和亚马逊的基础模型。&#xff08;Anthropic 就是之前跟 ChatGPT 掰手腕的 Claude 的模型。Stability AI 就是 Stable Diffusion 背后的…

外汇天眼:如何识破网络交友诈骗套路? 看到这7大特征请提高警觉

随着各种社群平台与交友APP不断推陈出新&#xff0c;现代人愈来愈习惯透过网路建立人际关系甚至谈恋爱。 但由于网络具有极高的匿名性&#xff0c;因此也成为诈骗温床&#xff0c;对社会造成相当严重的损失。 有鉴于此&#xff0c;外汇天眼根据一直以来收到针对黑平台的投诉与…

各省市30米分辨率DEM数据,推荐下载!

今天给大家推荐一个新数据 —— 各省市30米分辨率DEM数据&#xff01; 各省市30米分辨率DEM数据广泛应用于国土资源调查、水利水电工程、地质灾害预警、城市规划等领域&#xff0c;对于了解区域内的地形地貌、地形分析、土地利用等具有非常重要的意义。 网站搜索“citybox城市…

数据时代的新引擎:数据治理与开发,揭秘数据领域的黄金机遇!

文章目录 一、数据时代的需求二、数据治理与开发三、案例分析四、黄金机遇《数据要素安全流通》《Python数据挖掘&#xff1a;入门、进阶与实用案例分析》《数据保护&#xff1a;工作负载的可恢复性 》《Data Mesh权威指南》《分布式统一大数据虚拟文件系统 Alluxio原理、技术与…

Microsoft 365 与Office 365 有什么区别?

从2020年起&#xff0c;部分Office 365 品牌的订阅计划整合到了Microsoft 365中&#xff0c;虽然这更符合微软对产品战略的定位&#xff0c;但却增加了用户分辨这两种产品的难度。 文章目录 Office 365包含哪些内容Microsoft 365包含哪些内容Microsoft 365包含哪些订阅Microso…

2023中国视频云市场报告:腾讯云音视频解决方案份额连续六次蝉联榜首,加速全球化布局

近日&#xff0c;国际数据公司&#xff08;IDC&#xff09;发布了《中国视频云市场跟踪&#xff08;2023上半年&#xff09;》报告&#xff0c;腾讯云音视频的解决方案份额连续六次蝉联榜首&#xff0c;并在视频生产创作与媒资管理市场份额中排名第一。同时&#xff0c;在实时音…

为什么深度学习模型的预测结果为数据集均值

如图&#xff0c;上边的为真值&#xff0c;下边的为预测值&#xff0c;可见预测值都是在30左右 一直debug不出来。后来发现是loss处写错了 用的torch.nn.MSELoss(pred,target)&#xff0c;其中pred的size是(batchsize,1), target的size是(batchsize)&#xff0c;此时会有警告但…

vue 集成高德地图,点击图标,弹出van-action-sheet,一闪而过的问题探究

代码 <van-action-sheet v-model"sheetShow" title""><div class"van-list-vol"><van-col span"3"><div><van-imagestyle"height: 40px; width: 40px"round:src"hospital.orgUrl? hospita…

玻色量子“揭秘”之最大割(Max-Cut)问题与QUBO建模

Max-Cut问题简单地说&#xff0c;就是求一种分割方法。给定一张无向图, 将所有顶点分割成两群, 同时使得被切断的边数量最大&#xff0c;或边的权重最大。 QUBO&#xff08;Quadratic Unconstrained Binary Optimization&#xff09;问题即二次无约束二值优化问题&#xff0c;…

Vue3 + Vite + Ts + Router搭建项目

1、新建文件夹 从新建的文件夹cmd进入终端 2、安装vite—依据vite创建vue3项目 2.1、运行 npm init vitelatest2.2.1、输入项目名称 2.2.2、选择vue 2.2.3、选择TypeScript语言 3、安装依赖项 3.1、进入刚才创建的文件夹 cd vite-project 3.2、查看镜像 #查看当前源 npm con…

Windows ObjectType Hook 之 SecurityProcedure

1、背景 Object Type Hook 是基于 Object Type的一种深入的 Hook&#xff0c;比起常用的 SSDT Hook 更为深入。 有关 Object Type 的分析见文章 《Windows驱动开发学习记录-ObjectType Hook之ObjectType结构相关分析》。 这里进行的 Hook 为 其中之一的 SecurityProcedure。文章…

CDS(Core Data Service)Annotation 常用属性

1. 抬头信息 @UI: {headerInfo: {typeName: BP,typeNamePlural: BP,title:{type: #STANDARD, value:ApplyNumber},description:{value:Status}} }2. 行信息/分组 @UI.facet: [{id: bp_Tab1,purpose: #STANDARD,type: #FIELDGROUP_REFERENCE,// type: #LINEITEM_REFERENCE,labe…

【Linux】 OpenSSH_7.4p1 升级到 OpenSSH_9.4p1(亲测无问题,建议收藏)

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

lazarus:不安装任何驱动,直接使用csv文件作为数据集

目录 1 简介 2 需要的窗体控件很简单 3 定义字段并插入几条记录 4 其他操作 4.1 数据集保存为csv文件 4.2 清空数据 4.3 加载csv文件 5 运行程序 6 导出文件 1 简介 在某些数据操作需求特别简单的情况下&#xff0c;我们希望不要安装任何数据库&#xff0c;甚至连一个…

餐饮加盟信息展示预约小程序的内容如何

餐饮业规模持续增加&#xff0c;相关从业者逐渐增多&#xff0c;对中等规模以上的餐饮品牌来说&#xff0c;当有一定规模后除了开多家直营店外&#xff0c;还会开放招商加盟&#xff0c;扩展品牌、提升营收等。 由于餐饮加盟属于准属性业务&#xff0c;因此传统线下方式不太适…