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

Linux网络——UDP的运用

Linux网络——UDP的运用


文章目录

  • Linux网络——UDP的运用
    • 一、引入
    • 二、服务端实现
      • 2.1 创建socket套接字
      • 2.2 指定网络接口并bind
      • 2.3 接收数据并处理
      • 2.4 整体代码
      • 2.5 IP的绑定的细节
    • 三、用户端实现
      • 3.1 创建套接字
      • 3.2 指定网络接口
      • 3.3 发生数据并接收
      • 3.4 绑定问题
    • 四、代码
    • 五、UDP实现网络聊天室(简易版)


一、引入

在上一篇Linux网络——网络套接字中我们简述了TCP/UDP协议

其实网络通信的本质就是进程间通信,而进程间通信无非就是读和写(IO)

这篇文章我们借助UDP实现服务端(server)和客户端(client)进行通信
将所学理论运用到实践中

二、服务端实现

由于服务端是面向广大用户的,如果我们将IP地址写死,那么服务器将只能从我们写的哪个IP地址中接收信息
所以启动服务器是不需要IP地址的,它默认接收所以IP地址发来的信息

//static const std::string default_ip = "0.0.0.0";
static const uint16_t default_port = 8888;

2.1 创建socket套接字

调用系统接口socket函数,帮助我们创建套接字,本质是把文件和网卡关联起来
在这里插入图片描述

参数介绍:

domain:一个域,标识了这个套接字的通信类型(网络或者本地)
在这里插入图片描述

只用关注上面三个类,第一个与第二个AF_UNIX/AF_LOCAL表示本地通信,而AF_INET表示网络通信
type:套接字提供服务的类型
在这里插入图片描述
我们用UDP实现,所以使用SOCK_DGRAM
protocol:想使用的协议,默认为0即可,因为前面的两个参数决定了,就已经决定了是TCP还是UDP协议了

返回值:

成功则返回打开的文件描述符(指向网卡文件,其实就是文件描述符),失败返回-1

创建套接字的本质其实就是创建了一个文件描述符,并返回该文件描述符的值
只是该文件描述符是用于对应服务的网路数据传输

	_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0){lg.LogMessgae(Fatal, "socket error, sockfd : %d\n", _sockfd);exit(1);}lg.LogMessgae(Info, "socket success, sockfd : %d\n", _sockfd);

2.2 指定网络接口并bind

在这里插入图片描述

参数介绍:

socket:创建套接字的返回值
address:通用结构体(上一章Linux网络——网络套接字有详细介绍)
address_len:传入结构体的长度

我们要先定义一个sockaddr_in结构体,将结构体内对应的字段填充好,再将结构体作为参数传递
在这里插入图片描述

struct sockaddr_in {short int sin_family;           // 地址族,一般为AF_INET或PF_INETunsigned short int sin_port;    // 端口号,网络字节序struct in_addr sin_addr;        // IP地址unsigned char sin_zero[8];      // 用于填充,使sizeof(sockaddr_in)等于16
};

创建结构体后要先清空数据(初始化),我们可以用memset,也可以用系统接口:

#include <strings.h>void bzero(void *s, size_t n);

填充端口号的时候要注意端口号是两个字节的数据,涉及到大小端问题
在计算机中的普遍规定:在网络中传输的数据都是大端的
所以为了统一,无论我们机器是大端还是小端,在调用接口的时候,都将IP与端口号从主机序列转化为网路序列

端口号的接口

#include <arpa/inet.h>
// 主机序列转网络序列
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
// 网络序列转主机序列
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

IP的接口
对于IP,其实有两步:首先将字符串转换为整型,再解决大小端问题
系统给了直接能解决这两个问题的接口

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>int inet_aton(const char *cp, struct in_addr *inp);in_addr_t inet_addr(const char *cp);// 点分十进制字符串in_addr_t inet_network(const char *cp);char *inet_ntoa(struct in_addr in);struct in_addr inet_makeaddr(int net, int host);in_addr_t inet_lnaof(struct in_addr in);in_addr_t inet_netof(struct in_addr in);

这里的inet_addr就是把一个点分十进制的字符串转化成整数再进行大小端处理

我们在启动服务器的时候只需要传入端口号即可,IP默认为INADDR_ANY
即默认接收所有的IP

代码

        // 2. 指定网络接口// 初始化结构体struct sockaddr_in local;bzero(&local, sizeof(local)); // memsetlocal.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));if (n != 0){lg.LogMessgae(Fatal, "bind error\n");exit(2);}

2.3 接收数据并处理

服务端要获取到用户端发送过来的数据

在这里插入图片描述

参数说明:

sockfd:从哪个套接字读
buf:数据放入的缓冲区
len:缓冲区长度
flags:读取方式, 0代表阻塞式读取
src_addraddrlen:输出型参数,返回对应的消息内容是从哪一个客户端发出的。第一个是自己定义的结构体,第二个是结构体长度

    void Start(){char buffer[1024];for (;;){struct sockaddr_in peer;socklen_t len = sizeof(peer);ssize_t n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);if (n > 0){InetAddr addr(peer);buffer[n] = 0;std::cout << "client[" << addr.PrintDebug() << "]# " << buffer << std::endl;std::string task = _BackMessage(buffer);sendto(_sockfd, task.c_str(), task.size(), 0, (struct sockaddr *)&peer, len);}}}

现在我们想要知道是谁发送过来的消息,信息都被保存到了peer结构体中,我们知道IP信息在peer.sin_addr.s_addr
这是一个网络序列,要转成主机序列,其次为了方便观察,要把它转换成点分十进制
而这两个操作系统给了一个接口能够解决:

char *inet_ntoa(struct in_addr in);

同样获取端口号的时候也要由网络序列转成主机序列:

uint16_t ntohs(uint16_t netshort);

这里我对struct sockaddr_in进行了封装
单独写了一个类InetAddr用来专门读取struct sockaddr_in内的ip和端口号

#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>class InetAddr
{public:InetAddr(struct sockaddr_in &addr):_addr(addr){_ip = inet_ntoa(addr.sin_addr);_port = ntohs(addr.sin_port);}std::string Ip(){return _ip;}uint16_t Port(){return _port;}sockaddr_in Addr(){return _addr;}std::string PrintDebug(){std::string info = _ip;info += ":";info += std::to_string(_port);  // "127.0.0.1:4444"return info;}~InetAddr(){}private:std::string _ip;uint16_t _port;struct sockaddr_in _addr;
};

2.4 整体代码

#pragma once#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include "nocopy.hpp"
#include "Log.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cerrno>
#include <strings.h>
#include <string.h>
#include "InetAddr.hpp"
#include "stdlib.h"
#include <functional>//static const std::string default_ip = "0.0.0.0";
static const uint16_t default_port = 8888;
static const int default_fd = -1;
static const int default_size = 1024;using func_t = function<std::string(std::string)>;class UdpServer : public nocopy
{
public:UdpServer(func_t BackMessage,const uint16_t port = default_port): _port(port), _sockfd(default_fd),_BackMessage(BackMessage){}void Init(){ // 1. 创建socket_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0){lg.LogMessgae(Fatal, "socket error, sockfd : %d\n", _sockfd);exit(1);}lg.LogMessgae(Info, "socket success, sockfd : %d\n", _sockfd);// 2. 指定网络接口// 初始化结构体struct sockaddr_in local;bzero(&local, sizeof(local)); // memsetlocal.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));if (n != 0){lg.LogMessgae(Fatal, "bind error\n");exit(2);}}~UdpServer(){}private:std::string _ip;uint16_t _port;int _sockfd;func_t _BackMessage;
};

2.5 IP的绑定的细节

如果我们将IP绑定为127.0.0.1,这个IP地址叫做本地环回地址

它的作用就是用来做服务器代码测试的
意思就是如果我们绑定的IP是127.0.0.1的话,在应用层发送的消息不会进入物理层,也就不会发送出去
在这里插入图片描述

当我们运行起来后想要查看网络情况就可以用指令netstat
后边也可以附带参数:

-a:显示所有连线中的Socket;
-e:显示网络其他相关信息;
-i:显示网络界面信息表单;
-l:显示监控中的服务器的Socket;
-n:直接使用ip地址(数字),而不通过域名服务器;
-p:显示正在使用Socket的程序识别码和程序名称;
-t:显示TCP传输协议的连线状况;
-u:显示UDP传输协议的连线状况;

在这里插入图片描述

在这里插入图片描述

三、用户端实现

要发送数据给服务器,就得知道服务器的IP和端口号
这里的IP就必须指明,用来表示我是连接哪台服务器上的哪个进程

uint16_t _serverport;
std::string _serverip;
int _sockfd;

这里的IP和port指的是要发送给谁,也就是需要服务器的IP和端口号

创建套接字就跟前面的一样:

    //1. 创建socketint _sockfd = socket(AF_INET,SOCK_DGRAM,0);if(_sockfd < 0){lg.LogMessgae(Fatal, "socket error, sockfd : %d\n", _sockfd);exit(1);}lg.LogMessgae(Info, "socket success, sockfd : %d\n", _sockfd);

3.1 创建套接字

  	//1. 创建socketint _sockfd = socket(AF_INET,SOCK_DGRAM,0);if(_sockfd < 0){lg.LogMessgae(Fatal, "socket error, sockfd : %d\n", _sockfd);exit(1);}lg.LogMessgae(Info, "socket success, sockfd : %d\n", _sockfd);

3.2 指定网络接口

    //2. 指定网络接口struct sockaddr_in send;memset(&send,0,sizeof(send));send.sin_family = AF_INET;send.sin_port = htons(stoi(argv[2]));send.sin_addr.s_addr = inet_addr(argv[1]);

3.3 发生数据并接收

在这里插入图片描述

这里的参数和上面的recvfrom差不多,而这里的结构体内部我们要自己填充目的IP和目的端口号
也就是服务器的IP和端口号

 	//3. 发送消息while(true){std::string buffer;std::cout<<"Please Enter# ";getline(std::cin,buffer);//cout<<buffer<<endl;ssize_t n = sendto(_sockfd,buffer.c_str(),buffer.size(),0,(struct sockaddr*)&send,sizeof(send));if(n == -1){cout<<"error"<<endl;}if(n > 0){char rec[1024];//没用,但有必要struct sockaddr_in tmp;socklen_t len = sizeof(tmp);ssize_t m = recvfrom(_sockfd, rec, sizeof(rec) - 1, 0, (struct sockaddr *)&tmp, &len);if(m>0){rec[m] = 0;InetAddr addr(tmp);std::cout<<"server["<<addr.PrintDebug()<<"]# "<<rec<<std::endl;}else{break;}}else{break;}}

3.4 绑定问题

首先bind的作用是允许应用程序指定一个端口号用于监听传入的数据报或数据流

对于服务端:
需要绑定一个公开的端口号,允许大家访问,如果是随机的,其他人不知道,也就访问不了,所以服务端需要绑定

对于客户端:
客户端在给服务器发信息的同时,服务器也可能给客户端发信息,所以客户端为了监听服务器有没有给自己回信息也需要bind一个端口号用于监听,但客户端不需要显式的bind,因为客户端的端口号不会被所有人访问,别人不需要知道,所以OS自动帮我们bind一个随机的端口号,另外也是为了防止端口号重复,避免破坏唯一性

那么为什么前面服务端必须显示的绑定port呢?

因为服务器的端口号是众所周知的,不能改变,如果变了就找不到服务器了

而客户端只需要有就可以,只用标识唯一性即可
举个例子:

我们手机上有很多的app,而每个服务端是一家公司写的,但是客户端却是多个公司写的
如果我们绑定了特定的端口,万一两个公司都用了同一个端口号呢?这样就直接冲突了

OS会自动填充主机IP和随机生成端口号进行绑定(在发送数据的时候自动绑定)
所以创建客户端我们只用创建套接字即可

四、代码

UdpServer

#pragma once#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include "nocopy.hpp"
#include "Log.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cerrno>
#include <strings.h>
#include <string.h>
#include "InetAddr.hpp"
#include "stdlib.h"
#include <functional>//static const std::string default_ip = "0.0.0.0";
static const uint16_t default_port = 8888;
static const int default_fd = -1;
static const int default_size = 1024;using func_t = function<std::string(std::string)>;class UdpServer : public nocopy
{
public:UdpServer(func_t BackMessage,const uint16_t port = default_port): _port(port), _sockfd(default_fd),_BackMessage(BackMessage){}void Init(){ // 1. 创建socket_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0){lg.LogMessgae(Fatal, "socket error, sockfd : %d\n", _sockfd);exit(1);}lg.LogMessgae(Info, "socket success, sockfd : %d\n", _sockfd);// 2. 指定网络接口// 初始化结构体struct sockaddr_in local;bzero(&local, sizeof(local)); // memsetlocal.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));if (n != 0){lg.LogMessgae(Fatal, "bind error\n");exit(2);}}void Start(){char buffer[1024];for (;;){struct sockaddr_in peer;socklen_t len = sizeof(peer);ssize_t n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);if (n > 0){InetAddr addr(peer);buffer[n] = 0;std::cout << "client[" << addr.PrintDebug() << "]# " << buffer << std::endl;std::string task = _BackMessage(buffer);sendto(_sockfd, task.c_str(), task.size(), 0, (struct sockaddr *)&peer, len);}}}~UdpServer(){}private:std::string _ip;uint16_t _port;int _sockfd;func_t _BackMessage;
};#include "UdpServer.hpp"
#include <memory>void Usage(const std::string s)
{std::cout << "Usagr: " << s << " local_port" << std::endl;
}std::string BackMessage(const string s)
{return "Back Message# " + s;
}int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);return 1;}std::unique_ptr<UdpServer> usver(new UdpServer(BackMessage,std::stoi(argv[1])));usver->Init();usver->Start();return 0;
}

UdpClient

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include <memory.h>
#include "InetAddr.hpp"
#include <cstdio>
#include <string>
void usage(std::string s)
{std::cout<<"Usagr: "<<s<<" server_ip server_port"<<std::endl;
}int main(int argc,char *argv[])
{if(argc != 3){usage(argv[0]);return 0;}//1. 创建socketint _sockfd = socket(AF_INET,SOCK_DGRAM,0);if(_sockfd < 0){lg.LogMessgae(Fatal, "socket error, sockfd : %d\n", _sockfd);exit(1);}lg.LogMessgae(Info, "socket success, sockfd : %d\n", _sockfd);//2. 指定网络接口struct sockaddr_in send;memset(&send,0,sizeof(send));send.sin_family = AF_INET;send.sin_port = htons(stoi(argv[2]));send.sin_addr.s_addr = inet_addr(argv[1]);//3. 发送消息while(true){std::string buffer;std::cout<<"Please Enter# ";getline(std::cin,buffer);//cout<<buffer<<endl;ssize_t n = sendto(_sockfd,buffer.c_str(),buffer.size(),0,(struct sockaddr*)&send,sizeof(send));if(n == -1){cout<<"error"<<endl;}if(n > 0){char rec[1024];//没用,但有必要struct sockaddr_in tmp;socklen_t len = sizeof(tmp);ssize_t m = recvfrom(_sockfd, rec, sizeof(rec) - 1, 0, (struct sockaddr *)&tmp, &len);if(m>0){rec[m] = 0;InetAddr addr(tmp);std::cout<<"server["<<addr.PrintDebug()<<"]# "<<rec<<std::endl;}else{break;}}else{break;}}return 0;
}

运行图:

在这里插入图片描述

在这里插入图片描述

五、UDP实现网络聊天室(简易版)

篇幅有限,只放gitee链接:UDP实现网络聊天室(简易版)

相关文章:

Linux网络——UDP的运用

Linux网络——UDP的运用 文章目录 Linux网络——UDP的运用一、引入二、服务端实现2.1 创建socket套接字2.2 指定网络接口并bind2.3 接收数据并处理2.4 整体代码2.5 IP的绑定的细节 三、用户端实现3.1 创建套接字3.2 指定网络接口3.3 发生数据并接收3.4 绑定问题 四、代码五、UD…...

axios

文章目录 [TOC](文章目录) 一、axios的基本使用axios请求1、引用axios,并发送请求axios发送请求的简化写法2、接受响应数据&#xff0c;并对响应的数据进行处理 三、axios拦截器&#xff08;instance&#xff09;1、请求拦截2、响应拦截 axios拦截器、vue中的路由守卫、servlet…...

MacOS下TestHubo安装配置指南

TestHubo是一款开源免费的测试管理工具&#xff0c; 下面介绍MacOS私有部署的安装与配置。TestHubo 私有部署版本更适合有严格数据安全要求的企业&#xff0c;支持在本地或专属服务器上运行&#xff0c;以实现对数据和系统的完全控制。 1、Mac 服务端安装 Mac安装包下载地址&a…...

vue2/3,Spring Boot以及生产环境跨域解决方案

vue2和vue3跨域解决方案 Vue 2 (基于 Webpack) 的跨域解决方案 1. 创建或编辑 vue.config.js 文件 Vue CLI为Webpack项目提供了简单的代理配置方式。你可以通过创建或编辑项目的根目录下的 vue.config.js 文件来设置开发服务器的代理规则&#xff1a; // vue.config.js mod…...

TestMAX/DFT Compiler:时序单元的类型、连接顺序和后DFT优化

相关阅读 TestMAX/DFT Compilerhttps://blog.csdn.net/weixin_45791458/category_12865937.html?spm1001.2014.3001.5482 时序单元的状态 未映射的时序单元(Unmapped Sequential Cell) 在Design Compiler读取了一个RTL设计后&#xff0c;Design Compiler内置的HDL Compiler工…...

Elasticsearch:analyzer(分析器)

一、概述 可用于将字符串字段转换为单独的术语&#xff1a; 添加到倒排索引中&#xff0c;以便文档可搜索。级查询&#xff08;如 生成搜索词的 match查询&#xff09;使用。 分析器分为内置分析器和自定义的分析器&#xff0c;它们都是由若干个字符过滤器&#xff08;chara…...

蓝桥杯——异或森林

问题描述 在一个神秘的世界中&#xff0c;存在着一个称为"异或森林"的地方。异或森林中的每个树木都拥有独特的力量。肖恩进入了这片森林&#xff0c;他得到了一个任务&#xff1a;找出数组中满足条件的连续子数组&#xff0c;使得连续子数组中所有元素异或运算结果…...

第一个C++程序 - Hello World, 编译与运行

引言 编写并运行你的第一个 C 程序是学习这门语言的第一步。通过这个简单的例子&#xff0c;你将了解如何创建、编译和运行一个基本的 C 程序。本文将详细介绍每个步骤&#xff0c;并确保初学者能够顺利上手。 一、编写 "Hello World" 程序 1. 创建源代码文件 首先…...

学习threejs,PerspectiveCamera透视相机和OrthographicCamera正交相机对比

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.PerspectiveCamera透…...

测试 - 4 ( 9000 字详解 )

一&#xff1a;性能测试 1.1 什么是性能测试 性能测试和功能测试虽然都在系统测试阶段进行&#xff0c;但两者有本质区别。功能测试主要关注系统“能否完成特定功能”&#xff0c;例如一辆车是否具备四个轮子、方向盘、挡风玻璃&#xff0c;以及是否能够正常行驶。而性能测试…...

从 Coding (Jenkinsfile) 到 Docker:全流程自动化部署 Spring Boot 实战指南(简化篇)

前言 本文记录使用 Coding (以 Jenkinsfile 为核心) 和 Docker 部署 Springboot 项目的过程&#xff0c;分享设置细节和一些注意问题。 1. 配置服务器环境 在实施此过程前&#xff0c;确保服务器已配置好 Docker、MySQL 和 Redis&#xff0c;可参考下列链接进行操作&#xff1…...

NIPS2014 | GAN: 生成对抗网络

Generative Adversarial Nets 摘要-Abstract引言-Introduction相关工作-Related Work对抗网络-Adversarial Nets理论结果-Theoretical Results实验-Experiments优势和不足-Advantages and disadvantages缺点优点 结论及未来工作-Conclusions and future work研究总结未来研究方…...

WebGPU入门初识

什么是 WebGPU&#xff1f; WebGPU 是一种现代图形 API&#xff0c;旨在取代 WebGL&#xff0c;提供更高性能和更灵活的 GPU 加速能力。它基于 Vulkan、Metal 和 Direct3D 12&#xff0c;为 Web 开发者带来了类似于原生图形 API 的性能和控制力。 与 WebGL 不同&#xff0c;Web…...

Go语言基础语法

文章目录 Go语言基础语法一、引言二、基础语法1、变量声明与作用域1.1、全局变量1.2、局部变量1.3、块作用域 2、基本数据类型3、控制流程3.1、条件语句3.2、循环语句 4、函数5、并发编程 三、使用示例四、并发编程示例五、变量作用域详解六、总结 Go语言基础语法 一、引言 G…...

易基因: BS+ChIP-seq揭示DNA甲基化调控非编码RNA(VIM-AS1)抑制肿瘤侵袭性|Exp Mol Med

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 肝细胞癌&#xff08;hepatocellular carcinoma&#xff0c;HCC&#xff09;早期复发仍然是一个具有挑战性的领域&#xff0c;其中涉及的机制尚未完全被理解。尽管微血管侵犯&#xff08…...

layui动态拼接生成下拉框验证必填项失效问题

利用 jQuery 动态拼接下拉框时&#xff0c;lay-verify"required" 失效了&#xff0c;有以下几种原因。 1. <form></form>标签 加入 layui 类&#xff0c;class"layui-form" 。提交按钮上加自动提交&#xff0c;lay-submit ""; 。需…...

Speckly:基于Speckle文档的RAG智能问答机器人

前言 Speckly 是一个基于 检索增强生成 (RAG) 技术的智能问答机器人&#xff0c;它能像一位经验丰富的工程师&#xff0c;理解你的问题&#xff0c;并从 Speckle 文档中精准地找到答案。更厉害的是&#xff0c;它甚至可以帮你生成代码片段&#xff01;&#x1f680; 本文将详…...

NodeRed使用心得,实现增删改查等

使用场景介绍 在VUE中使用nodeRed实现对节点的 增删改查等功能&#xff0c;且储存成功之后下点击时启动对应流程 安装与配置 1.安装NodeRed npm install -g --unsafe-perm node-red 安装完成后&#xff0c;你可以通过运行以下命令来启动Node-RED node-red-start2. 配置文件 N…...

万物皆有解法(序)

万物皆有解法&#xff08;序&#xff09; 《万物有解》一&#xff1a;解的存在 解&#xff1a;可做解释解答&#xff0c;此文引申为原因。可做解除、解围&#xff0c;此文引申为解法、方法。 先有事物存于世-what&#xff0c;再有原因为何存-why&#xff0c;再有解法如何除去…...

OpenCV相机标定与3D重建(37)计算两幅图像之间单应性矩阵(Homography Matrix)的函数findHomography()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 找到两个平面之间的透视变换。 cv::findHomography 是 OpenCV 库中用于计算两幅图像之间单应性矩阵&#xff08;Homography Matrix&#xff09;的…...

从虚拟到现实:AI与AR/VR技术如何改变体验经济?

引言&#xff1a;体验经济的崛起 在当今消费环境中&#xff0c;产品与服务早已不再是市场竞争的唯一焦点&#xff0c;能够提供深刻感知和独特体验的品牌&#xff0c;往往更能赢得消费者的青睐。这种转变标志着体验经济的崛起。体验经济不仅仅是简单的买卖行为&#xff0c;而是通…...

Linux系统之stat命令的基本使用

Linux系统之stat命令的基本使用 一、stat命令 介绍二、stat命令帮助2.1 查询帮助信息2.2 stat命令的帮助解释 三、stat命令的基本使用3.1 查询文件信息3.2 查看文件系统状态3.3 使用格式化输出3.4 以简洁形式打印信息 四、注意事项 一、stat命令 介绍 stat 命令用于显示文件或文…...

c++ 命名空间

目录 目录 目录 namespace的定义 代码演示 先使用全局域&#xff0c;再使用namespace定义出的域 命名空间中可以定义变量/函数/类型等 命名空间可以嵌套 namespace的使用 指定命名空间访问 using将命名空间中某个成员展开 展开命名空间中全部成员 在c中&#xff0c;由…...

【实验记录】动手实现一个简单的神经网络实验(一)

最近上了“神经网络与深度学习”这门课&#xff0c;有一个自己动手实现调整神经网络模型的实验感觉还挺有记录意义&#xff0c;可以帮我巩固之前学习到的理论知识&#xff0c;所以就打算记录一下。 实验大概是使用LeNet&#xff08;卷积神经网络&#xff09;对MINIST数据集做图…...

【2024年最新】BilibiliB站视频动态评论爬虫

废话不多说&#xff0c;直接先放git仓库&#xff1a;GitHub - linyuye/Bilibili_crawler: bilibili爬虫&#xff0c;基于selenium获取oid与cookie&#xff0c;request获取api内容 〇&#xff1a;概念简述 oid&#xff1a;视频/动态的uuid&#xff0c;b站对于发布内容的通用唯…...

清空DNS 缓存

如果遇到修改了host文件&#xff0c;但是IP和域名的映射有问题的情况&#xff0c;可以尝试刷新DNS缓存。 ipconfig/flushdns win建加R建&#xff0c;然后输入cmd&#xff0c;然后回车 然后回车&#xff0c;或者点击确定按钮。 出现如下所示标识清空DNS 缓存成功。...

东土智能交通服务器助力北京市车路云一体化建设

背景及意义 北京高级别自动驾驶示范区自2020年启动建设&#xff0c;至今已经发展建设到3.0阶段&#xff0c;通州区作为3.0阶段扩建的重点区域之一&#xff0c;扩区建设范围共计约175平方公里&#xff0c;涉及18个属地街镇&#xff0c;涵盖580个路口。 作为北京市车路云一体化…...

HarmonyOS NEXT 实战之元服务:静态案例效果---妙语集语

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; import { authentication } …...

python基础项目

1.联系人案例 # 导入的模块 from input_util import * import re import csv# 定义一个变量保存文件读取的信息 users {}# 封装读取文件的函数 def reader_file(path_name: str ./python基础/2024-11-15python基础项目/data/a.csv) -> None:try:with open(path_name, enco…...

mysql返回N/A

在写统计图的接口&#xff0c;sql查询一直无数据&#xff0c;给的默认值也没有实现&#xff1a; SELECTifnull( unit.num, 0 ) riskUnitCount,ifnull( EVENT.num, 0 ) riskEventCount,ifnull( measure.num, 0 ) riskMeasureCount FROMtb_companyLEFT JOIN (SELECTrisk.qyid,co…...

C++---------迭代策略与迭代器

一、迭代策略与迭代器 迭代器的概念 迭代器是一种对象&#xff0c;它提供了一种统一的方式来访问容器&#xff08;如数组、向量、列表等&#xff09;中的元素&#xff0c;而不暴露容器的内部结构。迭代器的行为类似于指针&#xff0c;可以用于遍历容器中的元素、修改元素以及…...

深入解析 Oracle 的聚合函数 ROLLUP

目录 深入解析 Oracle 的聚合函数 ROLLUP一、ROLLUP 函数概述二、ROLLUP 函数语法三、ROLLUP 实例详解&#xff08;一&#xff09;基础分组聚合&#xff08;二&#xff09;引入 ROLLUP 函数&#xff08;三&#xff09;ROLLUP 与 NULL 值&#xff08;四&#xff09;多列复杂分组…...

kipotix4靶机实战

信息收集 1.判断靶机ip 原理&#xff1a;开靶机之前nmap扫一次网段&#xff0c;再开靶机之后扫一次&#xff0c;查看多出来的ip就是靶机ip ip192.168.98.1742.判断端口服务&#xff0c;系统版本 a.确定端口 b.-p指定端口进一步收集 c.信息筛选 1.端口&#xff1a;22,80,139,…...

Java中处理if-else的几种高级方法

前言 在我看来多写几个if-else没啥大不了的&#xff0c;但是就是看起来没啥逼格&#xff0c;领导嫌弃。我根据开发的经历写几个不同的替代方法 一、枚举法替代 我先前写了一篇文章&#xff0c;可以去看看。 通过枚举替换if-else语句的解决方案_枚举代替if else c语言-CSDN博…...

LaTeX 是一种基于标记的排版系统,广泛用于创建高质量的文档,特别是在需要复杂数学公式、表格、文献引用等的场景中

LaTeX 是一种基于标记的排版系统&#xff0c;广泛用于创建高质量的文档&#xff0c;特别是在需要复杂数学公式、表格、文献引用等的场景中。以下是关于 LaTeX 的详细解释&#xff1a; 1. LaTeX 的基本概念 本质&#xff1a;LaTeX 是基于 TeX 的排版系统&#xff0c;提供了更高…...

Go入门篇:(一)golang的安装和编辑工具安装

一、前言 最近我有幸接触到Go语言,深入了解后,发现go语言确实有很多让人惊叹的地方。作为一个有着多年Java编程经验的程序员,我深深地被它所吸引,并且决定记录下我的学习之路,以便与大家分享我的经验和感悟。 与Java不同,Go语言的语法和运行效率都非常高,特别是对于并…...

【10】Selenium+Python UI自动化测试 邮件发送测试报告(某积载系统实例-04)

测试报告需要发送给相关人员&#xff0c;但每次都要在report目录下去复制太麻烦&#xff0c;可以使用邮件模块自动将生成的报告发送给相关人员 1、 新增utils文件夹&#xff0c;用于存放工具文件 在utils下新增sendmail.py文件 代码 sendmail.py import smtplib from email.…...

Playwright爬虫xpath获取技巧

示例一 <button class"MuiButtonBase-root MuiButton-root MuiLoadingButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeLarge MuiButton-containedSizeLarge MuiButton-colorPrimary MuiButton-fullWidth MuiButton-root MuiLoadingButton…...

运算符 - 算术、关系、逻辑运算符

引言 在编程中&#xff0c;运算符是用于执行特定操作的符号。C 提供了多种类型的运算符&#xff0c;包括算术运算符、关系运算符和逻辑运算符等。理解这些运算符及其用法对于编写高效且无误的代码至关重要。本文将详细介绍 C 中的这三种基本运算符&#xff0c;并通过实例帮助读…...

中关村科金外呼机器人智能沟通破解营销难题

当今&#xff0c;传统的营销方式在效率、成本控制、客户管理等方面逐渐显现出局限性&#xff0c;难以满足现代企业的需求。如何提升营销效率、降低运营成本、有效管理客户会员&#xff0c;成为企业的难题。中关村科金外呼机器人通过智能化沟通技术&#xff0c;为企业提供了一站…...

css绘制圆并绘制圆的半径

<div class"item1"></div>.item1 {position: relative;width: 420px;height: 420px;border-radius: 50%; /* 圆形 */color: white; /* 文本颜色 */background-color: rgba(154, 227, 36, 0.4); } .item1::before {content: "";position: absol…...

实现类似gpt 打字效果

1. css的动画&#xff08;animation) css中实现动画有两种方式&#xff1a;transition过渡动画、 animation自定义动画。 具体的可以看MDN链接&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation 使用keyframes自定义关键帧动画并未其命名使用自定义动…...

【乐企文件生成工程】根据特定要素动态选择需要生成的发票板式文件实现

乐企版式文件生成工程,涉及到多个票种,不乏特殊票种的生成,如果每个特殊票种都单独写逻辑,那整个代码写起来体量就不得了,如何实现代码逻辑的同时也更优雅的实现代码扩展性呢,您接着往下看。 使用设计模式 工厂模式 1、定义接口InvoiceFileService public interface Inv…...

near-synonym反义词生成(2):Prompt +Bert-MLM(FT)

near-synonym之反义词生成方法二 near-synonym, 中文反义词/近义词/同义词(antonym/synonym)工具包. 方法一为(neg_antonym): Word2vec -> ANN -> NLI -> Length 方法二为(mlm_antonym): Prompt Bert-MLM(FT) Beam-Search 项目地址 github: https://github.com/yon…...

dockfile 配置 /etc/apt/source.list.d/debian.list 清华镜像

docker:3.12.7 镜像使用的是 debian 系统&#xff0c;比 ubuntu 更轻量。debian 系统内&#xff0c;apt 镜像源列表位于 /etc/apt/source.list.d/debian.list&#xff08;作为对比&#xff0c;ubuntu 的镜像列表位于 /etc/apt/source.list&#xff0c;二者语法相同&#xff09;…...

DAY38|动态规划Part06|LeetCode:322. 零钱兑换、279.完全平方数、139.单词拆分

目录 LeetCode:322. 零钱兑换 基本思路 C代码 LeetCode:279.完全平方数 C代码 LeetCode:139.单词拆分 基本思路 C代码 LeetCode:322. 零钱兑换 力扣题目链接 文字讲解&#xff1a;LeetCode:322. 零钱兑换 视频讲解&#xff1a;动态规划之完全背包&#xff0c;装满背包最…...

Spring事务回滚

Transactional注解 Transactional作用&#xff1a;就是在当前这个方法执行开始之前来开启事务&#xff0c;方法执行完毕之后提交事务。如果在这个方法执行的过程当中出现了异常&#xff0c;就会进行事务的回滚操作。 Transactional注解&#xff1a;我们一般会在业务层当中来控制…...

【目标跟踪】checkpoint文件到底是什么?

说实话&#xff0c;我一直决定计算机视觉是个很玄的东西&#xff0c;里面的很多东西都是看了概念之后云里雾里&#xff0c;今天就把我复现代码时遇到的不懂得讲一讲——checkpoint文件是个啥&#xff1f; checkpoint文件顾名思义就是一个模型检查点文件&#xff0c;用于保存训练…...

hiprint结合vue2项目实现静默打印详细使用步骤

代码地址是&#xff1a;vue-plugin-hiprint: hiprint for Vue2/Vue3 ⚡打印、打印设计、可视化设计器、报表设计、元素编辑、可视化打印编辑 本地安装包地址&#xff1a;electron-hiprint 发行版 - Gitee.com 1、先安装hipint安装包在本地 2、项目运行npm&#xff08;socket.…...

apt和apt-get软件包管理工具-debian

apt 和 apt-get 是在基于Debian的Linux发行版&#xff08;如Ubuntu&#xff09;中使用的两个软件包管理工具&#xff0c;它们都属于APT&#xff08;Advanced Package Tool&#xff09;的前端工具&#xff0c;用于管理软件包的安装、更新、升级和删除。以下是它们的特性和一些比…...