当前位置: 首页 > news >正文

【Linux网络】:套接字之UDP

一、UDP和TCP协议

TCP (Transmission Control Protocol 传输控制协议)的特点:

  • 传输层协议
  • 连接(在正式通信前要先建立连接)
  • 可靠传输(在内部帮我们做可靠传输工作)
  • 面向字节流

UDP (User Datagram Protocol 用户数据报协议)的特点:

  • 传输层协议
  • 连接
  • 不可靠传输(可能会出现网络丢包或数据包乱序、重复等问题)
  • 面向数据报

 

        UDP和TCP协议都是隶属于传输层的协议,并且这两个协议距离用户来说是最近的。所以一般以数据通信为目的的代码都是使用的是关于传输层提供的这些接口,那在传输层提供的协议总共有UDP和TCP两种协议。

        其中TCP协议被叫做是传输控制协议,并且它的特点是有连接,可靠传输,面向字节流这些特点,这些特点会在后续进行讨论,而UDP协议是用户数据包协议,它的特点是无连接,不可靠传输,面向数据报。现在只是需要知道的是,TCP协议对于传输的内容要进行严格的追踪,必须要确保这个数据包能够完整的被对方接受了才会善罢甘休,而对于UDP来说却不是这样,它只保证自己发送了这个数据即可,至于对方有没有接受到这个信息不属于它的关心范围。

可能你会质疑UDP的传输,这是不是也意味着UDP的传输就不如TCP呢?为什么还要用UDP?

        其实这两个概念都是中性词,并没有说到底是哪个协议就好,哪个协议就坏,TCP的传输虽然很稳定,不可置疑,但是带来的问题是追踪每一个包的相关信息到底有没有送达就意味着需要消耗额外的资源来进行管理,而对比UDP来说就没有这些额外的消耗,所以并没有一个严格的定义哪个就比哪个更优,只是在特定的场景可能会略有区分。

    二、网络字节序

    首先要清楚大小端的概念:

    • 小端:低权值的数放入低地址。
    • 大端:低权值的数放入高地址。

    我们已经知道, 内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分。

    如何定义网络数据流的地址呢?(如果一个大端机用大端的方式发送数据到一个小端机,现在跨网络我们也不知道数据到底是大端和小端) 在网络诞生之前,就已经有了大小端的概念了,但是大小端到底谁好谁坏?这其实很难做出一个具体的区分,不同的技术厂商会采取不同的使用方法,但是网络诞生之后,必须解决的问题是数据到底是用小端来传输还是用大端来传输,如果不解决这个问题就无法进行适当的网络传输。

    那怎么办呢?最终网络选择的一个方法是,不管是大端机器还是小端机器,只要想要在网络上传输,必须传递的是大端数据,换句话说大端机器的数据就可以直接在网络上进行传输,但是小端机器的数据就必须要进行合适的转换才可以,所以也对应的提供了一套接口,来表示把数据进行转换:

    1. h 表示 host,n 表示 network,l 表示 32 位长整数,s 表示 16 位短整数。
    2. 例如 htonl 表示将 32 位的长整数从主机字节序转换为网络字节序,例如将 IP 地址转换后准备发送。
    3. 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
    4. 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。

    三、socket套接字 

    socket编程常见的接口

    // 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
    int socket(int domain, int type, int protocol);
    // 绑定端口号 (TCP/UDP, 服务器)
    int bind(int socket, const struct sockaddr *address,
    socklen_t address_len);
    // 开始监听socket (TCP, 服务器)
    int listen(int socket, int backlog);
    // 接收请求 (TCP, 服务器)
    int accept(int socket, struct sockaddr* address,
    socklen_t* address_len);
    // 建立连接 (TCP, 客户端)
    int connect(int sockfd, const struct sockaddr *addr,
    socklen_t addrlen);
    

    未来在进行写套接字的时候,一般默认情况下是需要把本主机的ip地址和端口号这样的套接字信息,通过系统调用来和对应打开的网络套接字来进行绑定,那么其中网络套接字也有很多的类型,例如:

    1. 域间套接字
    2. 原始套接字
    3. 网络套接字

    域间套接字:它的侧重点更多是同一个机器内,这个域表示的是你的机器本身,在里面进行套接,有点类似于之前管道的概念,通过文件路径的方式标识一份公共资源,然后再以套接字的方式实现双方的通信,这个就是域间套接字。其中域间套接字表示的是本地通信

    原始套接字:看做它是一个网络工具,它一般是绕过传输层,使用底层的一些接口来进行开发工具,比如说来进行检查计算机当前是否联通,比如要进行抓包等等行为,都是借助原始套接字来进行完成的。

    网络套接字:通常是用来标识用户之间的网络通信,也是本篇的重点内容,是指使用TCP或者是UDP的协议来实现了用户间的数据通信

    在这之中有一个需要注意的点,那就是网络接口的设计者想要做成的效果是,理论上来说未来的不同套接字可能需要三套接口,但是他并不想这样设计,他想要进行高度抽象出一套共同的接口,来方便进行使用,但是现在的问题是他该如何进行保证网络接口的统一的呢?接口想要统一,第一个面临的问题就是参数必须统一,可是该如何解决这个问题呢?

    在真实情况下进行网络通信的时候,使用的结构体里面首先要包含16位的端口号,还有30位的ip地址,还有8位的填充等等,但是如果想用一个接口来实现,就意味着要想办法克服让不同的人看到参数后能转换成自己的资源,那对应的解决方案是,不管是网络通信还是本地通信,对应的前2个字节,就表明了通信的类型,如下图所示:

    可以看到 sockaddr_in 和 sockaddr_un 是两个不同的通信场景,区分它们就用 16 地址类型协议家族的标识符。但是,这两个结构体都不用,我们用 sockaddr。

    比方说我们想用网络通信,虽然参数是 const struct sockaddr *addr,但实际传递进去的却是 sockaddr_in 结构体(注意要强制类型转换)。在函数内部一视同仁,全部看成 sockaddr 类型,然后根据前两个字节判断到底是什么通信类型然后再强转回去。可以把 sockaddr 看成基类,把 sockaddr_in 和 sockaddr_un 看成派生类,构成了多态体系。

    • IPv4 和 IPv6 的地址格式定义在 netinet/in.h 中,IPv4 地址用 sockaddr_in 结构体表示,包括 16 位地址类型,16 位端口号和 32 位 IP 地址。
    • IPv4、IPv6 地址类型分别定义为常数 AF_INET、AF_INET6。这样,只要取得某种 sockaddr 结构体的首地址,不需要知道具体是哪种类型的 sockaddr 结构体,就可以根据地址类型字段确定结构体中的内容。
    • socket API 可以都用 struct sockaddr * 类型表示, 在使用的时候需要强制转化成 sockaddr_in,这样的好处是程序的通用性,可以接收 IPv4,IPv6,以及 UNIX Domain Socket 各种类型的 sockaddr 结构体指针做为参数。

    每一种通信结构体的前面部分都是一样的,这也就意味着当需要进行匹配的时候,会首先匹配一下前两个字节,看前两个字节是哪种结构体的,进而就可以进行区分开了,所以最终,我们对应的网络套接字在使用的时候需要进行对应的强转,转换成所需要的具体的结构体就可以了,有点类似于void的概念,不过由于当时还没有出现void的概念,所以也就沿用至今了,在使用的时候直接看成是void*来使用就没有什么使用压力了。

    sockaddr 结构

    sockaddr_in 结构

     

    虽然  socket api  的接口是  sockaddr, 但是我们真正在基于  IPv4  编程时, 使用的数据结构是  sockaddr_in, 这个结构里主要有三部分信息: 地址类型, 端口号, IP  地址。

    in_addr 结构 

    四、UDP网络编码 

    这个文件的主要作用就是可以打印一些日志信息,用来方便编程测试代码:

    // Log.hpp
    #pragma once
    #include <iostream>
    #include <time.h>
    #include <stdarg.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdlib.h>#define SIZE 1024
    #define Info 0
    #define Debug 1
    #define Warning 2
    #define Error 3
    #define Fatal 4
    #define Screen 1
    #define Onefile 2
    #define Classfile 3
    #define LogFile "log.txt"class Log
    {
    public:Log(){printMethod = Screen;path = "./log/";}void Enable(int method){printMethod = method;}std::string levelToString(int level){switch (level){case Info:return "Info";case Debug:return "Debug";case Warning:return "Warning";case Error:return "Error";case Fatal:return "Fatal";default:return "None";}}void printLog(int level, const std::string &logtxt){switch (printMethod){case Screen:std::cout << logtxt << std::endl;break;case Onefile:printOneFile(LogFile, logtxt);break;case Classfile:printClassFile(level, logtxt);break;default:break;}}void printOneFile(const std::string &logname, const std::string &logtxt){std::string _logname = path + logname;int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); // "log.txt"if (fd < 0)return;write(fd, logtxt.c_str(), logtxt.size());close(fd);}void printClassFile(int level, const std::string &logtxt){std::string filename = LogFile;filename += ".";filename += levelToString(level); // "log.txt.Debug/Warning/Fatal"printOneFile(filename, logtxt);}~Log(){}void operator()(int level, const char *format, ...){time_t t = time(nullptr);struct tm *ctime = localtime(&t);char leftbuffer[SIZE];snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);va_list s;va_start(s, format);char rightbuffer[SIZE];vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);va_end(s);char logtxt[SIZE * 2];snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);printLog(level, logtxt);}private:int printMethod;std::string path;
    };
    
    // udpserver.hpp
    #pragma once
    #include <iostream>
    #include <string>
    #include <strings.h>
    #include <cstring>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <functional>
    #include "Log.hpp"
    using func_t = std::function<std::string(const std::string &)>;
    using namespace std;enum
    {SOCKET_ERROR = 1,BIND_ERROR
    };uint16_t defaultport = 8080;
    string defaultip = "0.0.0.0";
    const int size = 1024;
    Log lg;class UdpServer
    {
    public:UdpServer(const uint16_t &port = defaultport, const string &ip = defaultip): _sockfd(0), _port(port), _ip(ip), _isrunning(false){}void Init(){// 1. 创建UDP socket_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0){lg(Fatal, "socket create error, sockfd: %d", _sockfd);exit(SOCKET_ERROR);}lg(Info, "socket create success, sockfd: %d", _sockfd);// 2. 绑定socketstruct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = inet_addr(_ip.c_str());if (bind(_sockfd, (const struct sockaddr *)&local, sizeof(local)) < 0){lg(Fatal, "bind error, errno: %d, err string: %s", errno, strerror(errno));exit(BIND_ERROR);}lg(Info, "bind success, errno: %d, err string: %s", errno, strerror(errno));}void Run() // 对代码进行分层{_isrunning = true;char inbuffer[size];while (_isrunning){struct sockaddr_in client;socklen_t len = sizeof(client);ssize_t n = recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr *)&client, &len);if (n < 0){lg(Warning, "recvfrom error, errno: %d, err string: %s", errno, strerror(errno));continue;}inbuffer[n] = 0;string info = inbuffer;string echo_string = "sever echo#" + info;cout << echo_string << endl;sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (const sockaddr *)&client, len);}}~UdpServer(){if (_sockfd > 0)close(_sockfd);}private:int _sockfd;string _ip;uint16_t _port;bool _isrunning;
    };
    
    // udpclient.cc
    #include <iostream>
    #include <cstdlib>
    #include <unistd.h>
    #include <strings.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>using namespace std;void Usage(std::string proc)
    {std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
    }// ./udpclient serverip serverport
    int main(int argc, char *argv[])
    {if (argc != 3){Usage(argv[0]);exit(0);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);struct sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());socklen_t len = sizeof(server);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "socker error" << endl;return 1;}string message;char buffer[1024];while (true){cout << "Please Enter@ ";getline(cin, message);std::cout << message << std::endl;// 1. 数据 2. 给谁发sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&server, len);struct sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t s = recvfrom(sockfd, buffer, 1023, 0, (struct sockaddr *)&temp, &len);if (s > 0){buffer[s] = 0;cout << buffer << endl;}}close(sockfd);return 0;
    }
    
    // main.cc
    #include "UdpServer.hpp"
    #include <memory>
    using namespace std;void Usage(string proc)
    {cout << "\n\rUsage: " << proc << " port[1024+]\n"<< endl;
    }string ExcuteCommand(const std::string &cmd)
    {FILE *fp = popen(cmd.c_str(), "r");if (nullptr == fp){perror("popen");return "error";}std::string result;char buffer[4096];while (true){char *ok = fgets(buffer, sizeof(buffer), fp);if (ok == nullptr)break;result += buffer;}pclose(fp);return result;
    }int main(int argc, char *argv[])
    {if (argc != 2){Usage(argv[0]);exit(0);}uint16_t port = std::stoi(argv[1]);unique_ptr<UdpServer> svr(new UdpServer(port));svr->Init(/**/);svr->Run();return 0;
    }
    

    相关文章:

    【Linux网络】:套接字之UDP

    一、UDP和TCP协议 TCP &#xff08;Transmission Control Protocol 传输控制协议&#xff09;的特点&#xff1a; 传输层协议有连接&#xff08;在正式通信前要先建立连接&#xff09;可靠传输&#xff08;在内部帮我们做可靠传输工作&#xff09;面向字节流 UDP &#xff08;U…...

    量子威胁下的安全革命:后量子密码学技术路线与迁移挑战全解析

    引言 量子计算技术的快速发展正在重塑现代密码学的安全版图。随着Shor算法对传统公钥密码体系的根本性威胁[1]&#xff0c;全球范围内后量子密码学&#xff08;Post-Quantum Cryptography, PQC&#xff09;的研究与标准化进程已进入关键阶段。 本文基于权威文献分析&#xff0c…...

    多模态大语言模型(MLLM)- kimi-vl technical report论文阅读

    前言 kimi-vl是月之暗面团队于2025年4月10日发布的多模态大模型。 代码链接&#xff1a;https://github.com/MoonshotAI/Kimi-VL 背景 随着人工智能技术的快速发展&#xff0c;人们对AI助手的需求已从单一文本交互转向多模态理解。新一代多模态模型如GPT-4o和Gemini虽展现…...

    ai聊天流式响应,阻塞式和流式响应 nginx遇到的坑

    问题 现在做ai的流式请求&#xff0c;在开发环境使用代理访问接口&#xff0c;显示是正常的。上到正式环境&#xff0c;代理通过nginx配置可以访问到流式接口。在本地测试postman请求流式接口&#xff0c;返回的东西是流式返回&#xff0c; 在正式环境里面使用postman请求流式…...

    Linux安全模块:SELinux与AppArmor深度解析

    引言 在Linux安全领域&#xff0c;SELinux和AppArmor就像两位忠诚的"系统保镖"&#x1f482;&#xff0c;为你的服务器提供强制访问控制(MAC)保护&#xff01;本文将深入解析这两大安全模块的工作原理、配置方法和实战技巧。无论你是要加固Web服务器&#xff0c;还是…...

    FlinkJobmanager深度解析

    1. JobManager 概述 Flink 是一个分布式流处理框架&#xff0c;其核心组件包括 JobManager、TaskManager 和客户端&#xff08;如 CLI 或 Web UI&#xff09;。JobManager 是 Flink 集群的“大脑”&#xff0c;负责协调作业的整个生命周期&#xff0c;包括作业调度、资源管理、…...

    FlinkSql入门与实践

    一、为什么需要 Flink SQL&#xff1f; 传统 SQL 是面向静态数据的查询语言&#xff0c;而现代实时业务要求对动态数据流进行即时分析。Flink SQL 应运而生&#xff0c;它让开发者无需编写复杂的状态管理代码&#xff0c;就能实现实时ETL、复杂事件处理&#xff08;CEP&#x…...

    【物联网】基于LORA组网的远程环境监测系统设计(ThingsCloud云平台版)

    演示视频: 基于LORA组网的远程环境监测系统设计(ThingsCloud云平台版) 前言:本设计是基于ThingsCloud云平台版,还有另外一个版本是基于机智云平台版本,两个设计只是云平台和手机APP的区别,其他功能都一样。如下链接: 【物联网】基于LORA组网的远程环境监测系统设计(机…...

    C++中指针Ptr(一级指针、二级指针)的基本使用详解(1)

    C 中的指针是非常强大的工具&#xff0c;理解一级指针、二级指针以及它们与数组的关系&#xff0c;对于写出高效且安全的程序非常重要。下面我将从基础讲起&#xff0c;详细解释 一级指针、二级指针 的使用&#xff0c;注意事项&#xff0c;以及它们和数组之间的联系与区别&…...

    科技赋能建筑新未来:中建海龙模块化建筑产品入选中国建筑首批产业化推广产品

    在建筑工业化浪潮中&#xff0c;中国建筑国际集团旗下中建海龙科技有限公司&#xff08;以下简称“中建海龙”&#xff09;致力以科技创新赋能传统建造转型升级&#xff0c;大力发展新质生产力&#xff0c;促进科技成果在建筑产业体系化、规模化应用&#xff0c;面向“产品化、…...

    示例:Spring JDBC 声明式事务(xml配置形式)

    声明式事务是指在不修改源代码的情况下通过配置applicationContext.xml自动实现事务控制&#xff0c;其本质是AOP环绕通知。它的触发时机为&#xff1a;1、当目标方法执行成功时自动提交事务&#xff0c;2、当目标方法抛出运行时异常时&#xff0c;自动事务回滚 核心步骤示例&a…...

    java多线程(7.0)

    目录 ​编辑 定时器 定时器的使用 三.定时器的实现 MyTimer 3.1 分析思路 1. 创建执行任务的类。 2. 管理任务 3. 执行任务 3.2 线程安全问题 定时器 定时器是软件开发中的一个重要组件. 类似于一个 "闹钟". 达到一个设定的时间之后, 就执行某个指定好的…...

    sgpt在kali应用

    Kali Linux 下 sgpt 渗透测试相关案例 1. 扫描目标主机存活 sgpt -s "使用 nmap 扫描 192.168.1.100 是否存活"示例命令&#xff1a; nmap -sn 192.168.1.1002. 扫描目标主机开放端口和服务 sgpt -s "使用 nmap 扫描 192.168.1.100 常见端口和服务"示例…...

    小白电路设计-设计11-恒功率充电电路设计

    介绍 作为电子信息工程的我&#xff0c;电路学习是一定要学习的&#xff0c;可惜目前作为EMC测试工程师&#xff0c;无法兼顾太多&#xff0c;索性不如直接将所学的知识进行运用&#xff0c;并且也可以作为契机&#xff0c;进行我本人的个人提升。祝大家与我一起进行提升。1.本…...

    express的模板handlebars用app.engine()创建配置和用exphbs.create()的区别

    在使用 express-handlebars 时&#xff0c;app.engine 和 exphbs.create 都可以用来配置 Handlebars 模板引擎&#xff0c;但它们的使用方式和功能有一些区别。以下是详细的对比和说明 app.engine 方法 app.engine 是 Express 提供的方法&#xff0c;用于注册一个新的模板引擎…...

    【Python数据库与后端开发】从ORM到RESTful API

    目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心代码实现案例1&#xff1a;SQLAlchemy模型定义案例2&#xff1a;FastAPI异步接口案例3&#xff1a;连接池配…...

    数据结构(java)二叉树的基本操作

    1.二叉树的性质&#xff1a; 1.若规定根结点的层数为1&#xff0c;则一棵非空二叉树的第i层上最多有2*-1(i>0)个结点 2.若规定只有根节点的二叉树的深度为1&#xff0c;则深度为K的二叉树的最大结点数是2都k次方-1 3.对于任何一个二叉树&#xff0c;如果其叶结点个数为 n…...

    windows编程字符串处理

    提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、windows常用字符出处理函数&#xff1f;二、测试代码总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; Windows编程中主要使用两…...

    CentOS系统防火墙服务介绍

    CentOS 系统使用的是 firewalld 防火墙服务&#xff08;从 CentOS 7 开始&#xff09;&#xff0c;它基于 zone&#xff08;区域&#xff09; 和 service&#xff08;服务&#xff09; 的机制来配置网络访问控制&#xff0c;替代了传统的 iptables。 iptables 是 Linux 系统中…...

    59、微服务保姆教程(二)Nacos--- 微服务 注册中心 + 配置中心

    Nacos— 微服务 注册中心 + 配置中心 一.什么是Nacos? Nacos是阿里的一个开源产品,是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案。 Nacos核心定位是“一个更易于帮助构建云原生应用的动态服务发现、配置和服务管理平台”,也就是我们的注册中心和配…...

    Git命令行中vim的操作

    Git命令行用vim打开文件&#xff0c;或者用其他git命令打开了文件&#xff0c;需要编辑和保存文件等&#xff0c;有些命令表情奇怪&#xff0c;往往容易忘记这些命令。记录下。 下面这篇比较实用和简练&#xff1a; gitvim编辑文件命令 • Worktile社区https://worktile.com/…...

    【分布式系统中的“瑞士军刀”_ Zookeeper】一、Zookeeper 快速入门和核心概念

    在分布式系统的复杂世界里&#xff0c;协调与同步是确保系统稳定运行的关键所在。Zookeeper 作为分布式协调服务的 “瑞士军刀”&#xff0c;为众多分布式项目提供了高效、可靠的协调解决方案。无论是在分布式锁的实现、配置管理&#xff0c;还是在服务注册与发现等场景中&…...

    【昇腾】【训练】800TA2-910B使用LLaMA-Factory训练Qwen

    文章目录 1. 使用docker安装1.1 配置docker1. 2 拉取 LLaMA-Factory1.3 修改配置 2. 下载模型3. 准备训练数据3.1 下载数据集3.2 自定义数据集配置 4. 训练4.1 训练配置4.2 启动训练4.3 训练效果测试 5. 合并权重 更好的阅读体验&#xff1a;传送门 服务器&#xff1a;800TA2 芯…...

    Python自动化解决滑块验证码的最佳实践

    1. 引言&#xff1a;滑块验证码的挑战与自动化需求 滑块验证码&#xff08;Slider CAPTCHA&#xff09;是当前互联网广泛使用的反爬机制之一&#xff0c;它要求用户手动拖动滑块到指定位置以完成验证。这种验证方式可以有效阻止简单的自动化脚本&#xff0c;但对爬虫开发者来说…...

    知识蒸馏和迁移学习的区别

    知识蒸馏和迁移学习虽然都涉及知识的传递&#xff0c;但并不是同一个概念&#xff0c;它们在目的、方法和应用场景上有显著区别&#xff1a; 1. 定义与核心思想 迁移学习&#xff08;Transfer Learning&#xff09; 是一种广义的机器学习范式&#xff0c;核心是将从一个任务或领…...

    二项分布详解:从基础到应用

    二项分布详解&#xff1a;从基础到应用 目录 引言二项分布的定义概率质量函数及其证明期望与方差推导二项分布的重要性质常见应用场景与其他分布的关系知识梳理练习与思考 引言 概率论中&#xff0c;二项分布是最基础也是最常用的离散概率分布之一。它描述了在固定次数的独…...

    迁移学习(基础)

    迁移学习理论 目标 迁移学习中的有关概念掌握迁移学习的两种方式 概念 预训练模型微调微调脚本 预训练模型(Pretrained model) 一般情况下预训练模型都是大型模型, 具备复杂的网络结构, 众多的参数量, 以及足够大的数据集进行训练而产生的模型, 在NLP领域, 预训练模型往往…...

    云服务器和独立服务器的区别在哪

    在当今数字化的时代&#xff0c;服务器成为了支撑各种业务和应用的重要基石。而在服务器的领域中&#xff0c;云服务器和独立服务器是两个备受关注的选项。那么&#xff0c;它们到底有何区别呢&#xff1f; 首先&#xff0c;让我们来聊聊成本。云服务器通常采用按需付费的模式…...

    大模型时代的深度学习框架

    作者&#xff1a;算力魔方创始人/英特尔创新大使刘力 在CNN时代&#xff0c;AI模型的参数规模都在百万级别&#xff0c;仅需在单张消费类显卡上即可完成训练。例如&#xff0c;以业界知名的CNN模型&#xff1a;ResNet50为例&#xff0c;模型参数量是约为 25.63M&#xff0c;在…...

    BIOS主板(非UEFI)安装fedora42的方法

    BIOS主板(非UEFI)安装fedora42的方法 现实困难&#xff1a;将Fedora-Workstation-Live-42-1.1.x86_64.iso写入U盘制作成可启动U盘启动fedora42&#xff0c;按照向导将fedora42安装到真机的sda7分区中得到报错如下内容&#xff1a; /boot/efi 必需的 /boot/efi必须位于格式化为e…...

    C# 综合示例 库存管理系统7 主界面(FormMain)

    版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 图99A-22 主界面窗口设计 主界面是多文档界面容器,需要将窗体属性IsMdiContainer设置为True。关于多文档界面编程请参看教程第7.12节《多文档界面》。 主界面并不提…...

    1、RabbitMQ的概述笔记

    一、什么是RabbitMQ Rabbit是一个公司名.MQ(nessage queue) 消息队列的意思&#xff0c;RabbitMQ 是 Rabbit企业下的一个消息队列产品。 RabbitMQ 是⼀个实现了 AMQP 的 消息队列 服务,是当前主流的消息中间件之⼀. AMQP&#xff1a;即Advanced MessageQueuingProtocol(高级…...

    使用spring boot vue 上传mp4转码为dash并播放

    1.前端实现 <template><div class"video-upload"><el-uploadclass"upload-demo"action"/api/upload":before-upload"beforeUpload":on-success"handleSuccess":on-error"handleError":show-file-…...

    C++智能指针概念理解的面试题

    C智能指针概念理解的面试题 第一部分&#xff1a;基础概念 解释std::unique_ptr和std::shared_ptr在以下方面的区别&#xff1a; 所有权语义性能开销自定义删除器的存储方式是否支持数组类型 答案&#xff1a; 所有权语义&#xff1a; unique_ptr&#xff1a;独占所有权&#…...

    52.[前端开发-JS实战框架应用]Day03-AJAX-插件开发-备课项目实战-Lodash

    常用JavaScript库 1 认识前端工具库 前端工具类库 2 Lodash vs underscore underscore库 VS Lodash库 Lodash库 的安装 Lodash库字符串、数组 Lodash库对象、集合、函数 3 Day.js vs Mement Moment.js库 VS Day.js库 Day.js库安装 Day.js获取、设置、操作时间 Day.js解析、…...

    【论文阅读】平滑量化:对大型语言模型进行准确高效的训练后量化

    论文题目&#xff1a;SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models 论文地址&#xff1a;[2211.10438] SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models 代码地址&#xff1a;http…...

    mysql游标分页详解:让分页又快又稳的终极方案

    一、什么是游标分页&#xff1f; 游标分页是一种更高效的分页方式&#xff0c;它通过"记住当前位置"而不是"数页码"来实现分页。就像看书时夹书签一样&#xff0c;游标分页会记住你看到哪里了&#xff0c;下次直接从那里继续。 传统分页 vs 游标分页 传…...

    图论---染色法(判断是否为二分图)

    O(nm) 二分图&#xff1a;可以把所有的点划分到两边&#xff0c;使得边只在集合之间&#xff0c;集合内部没有边。 二分图当且仅当图中不含奇数环&#xff08;边数为奇数条&#xff09; #include <iostream> #include <vector> #include <cstring> using …...

    算法 | 基于SSA-CNN-LSTM(麻雀算法优化卷积长短期记忆神经网络)的股票价格预测(附完整matlab代码,公式,原理,可用于毕业论文设计)

    以下是一个基于SSA-CNN-LSTM(麻雀算法优化卷积长短期记忆神经网络)的股票价格预测MATLAB项目实例,包含完整代码和详细注释。代码分为数据预处理、模型构建、优化算法、训练预测四个部分。 🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜 1. 数据预处理 %% 数据加…...

    在html中如何创建vue自定义组件(以自定义文件上传组件为例,vue2+elementUI)

    1、先上代码&#xff1a;vueUpload.js var dom <div class"upload-file"><el-upload :action"uploadFileUrl" :before-upload"handleBeforeUpload" :file-list"fileList" :limit"limit":on-error"handleUpl…...

    Asp.Net Core 基于(asp.net core 2.2) 创建asp .net core空项目

    文章目录 ASP.NET Core 应用程序的标准入口点,用于配置和启动一个 Web 主机(WebHost)。`InProcess` 代码分析解决 HTTP Error 500.31 - Failed to load ASP.NET Core runtime 的完整方案**`launchSettings.json` 配置文件分析**ASP.NET Core 中的配置源详解ASP.NET Core 应用…...

    AiFlutter 低代码平台介绍

    产品概述 AiFlutter 低代码平台是一款基于拖拽组件和配置流程图的可视化开发工具&#xff0c;旨在简化移动应用开发过程。无需编写代码&#xff0c;用户即可通过拖拽组件快速搭建应用界面&#xff0c;并通过配置流程图设计页面逻辑。平台支持硬件通信功能&#xff0c;用户可直…...

    Flutter Dart 集合类型List Set Map详解军 以及循环语句 forEaclh map where any every

    List基础用法 var list1 ["西瓜", "苹果", "香蕉", true, 0];var list2 <String>["西瓜", "苹果", "香蕉"];List list3 ["西瓜", "苹果", "香蕉"];list3.add("草莓&…...

    aws(学习笔记第三十九课) iot-msk-pipeline

    文章目录 aws(学习笔记第三十九课) iot-msk-pipeline学习内容&#xff1a;1. 整体架构1.1 代码链接1.2 代码调整1.2 整体架构(概要)1.3 整体架构(详细) 2. 代码解析2.1 创建IotProducerDestination2.2 创建IotProducer2.3 创建MSK client的EC22.4 创建MSK cluster2.5 创建Main …...

    2025上海车展:赛轮思AI携手行业领军企业展示xUI——混合式、智能体化的AI助理平台

    用户将可首次全面体验集成多模态SLM (端侧大语言模型)的Cerence xUl&#xff0c;此次演示由长城汽车和TCL合作呈现 马萨诸塞州伯灵顿&#xff0c;2025年4月22日——Cerence Inc.&#xff08;NASDAQ: CRNC&#xff09;&#xff08;“赛轮思AI”&#xff09;&#xff0c;全球对话…...

    聚合分销小程序系统开发方案:整合AI对话、网盘、淘客CPS/CPA、电影票团购与会员卡业务

    一、系统架构设计 技术架构 分层设计&#xff1a;采用微服务架构&#xff0c;分为平台层&#xff08;分销管理、数据库、交易系统&#xff09;、管理体系层&#xff08;数据管理、权限控制&#xff09;和功能层&#xff08;AI对话、网盘、CPS/CPA拉新、电影票团购、会员卡&…...

    设计模式-- 原型模式详解

    原型模式&#xff08;prototype&#xff09; 原型模式&#xff1a;用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型相同或相似的新对象&#xff0c;原型模式属于创造性模式&#xff0c;它同样提供了创建对象的最佳方式之一。&#xff08;效率很高…...

    ARM服务器与X86服务器核心区别分析

    ARM服务器与X86服务器核心区别分析 一、架构设计与指令集差异 指令集本质‌ ARM‌&#xff1a;基于RISC&#xff08;精简指令集&#xff09;&#xff0c;指令定长且简单&#xff0c;单周期执行效率高&#xff0c;硬件设计复杂度低&#xff0c;适合低功耗场景。 X86‌&#xf…...

    嵌入式:ARM系列分类及主要应用场景

    在嵌入式系统和移动计算领域&#xff0c;Arm Cortex 系列处理器凭借其多样化的架构和卓越的性能&#xff0c;成为了众多设备的核心 “大脑”。从高端智能手机到工业控制设备&#xff0c;从物联网终端到安全芯片&#xff0c;Cortex 系列处理器以不同的型号和特性&#xff0c;满足…...

    Axure PR 9 中继器 标签

    大家好&#xff0c;我是大明同学。 这期内容&#xff0c;我们来了解一下Axure中继器数据表标签交互设计。 预览地址&#xff1a;https://n05kfs.axshare.com 好的&#xff0c;这里就结束了。 我是大明同学。 下期见。...