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_addr
和addrlen
:输出型参数,返回对应的消息内容是从哪一个客户端发出的。第一个是自己定义的结构体,第二个是结构体长度
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…...

项目亮点案例
其实对我来说是日常操作,但是如果在面试的时候面试者能把日常的事情总结好发出来,其实足矣。 想让别人认同项目,选取的示例需要包含以下要素: 亮点项目四要素:明确的目标,问题点,解决方法和结果…...
Retrofit源码分析:动态代理获取Api接口实例,解析注解生成request,线程切换
目录 一,Retrofit的基本使用 1.定义api接口 2.创建Retrofit实例 3.获取api接口实例发起请求 二,静态代理和动态代理 1,静态代理 2,动态代理 三,动态代理获取Api接口实例 四,解析接口方法注解&…...

范德蒙矩阵(Vandermonde 矩阵)简介:意义、用途及编程应用
参考: Introduction to Applied Linear Algebra – Vectors, Matrices, and Least Squares Stephen Boyd and Lieven Vandenberghe 书的网站: https://web.stanford.edu/~boyd/vmls/ Vandermonde 矩阵简介:意义、用途及编程应用 在数学和计算科学中&a…...

【中标麒麟服务器操作系统实例分享】java应用DNS解析异常分析及处理
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://document.kylinos.cn 情况描述 中标麒麟服务器操作系统V7运行在 ARM…...

网安瞭望台第17期:Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析
国内外要闻 Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析 在网络安全的复杂战场中,近期出现了一个值得关注的动态:名为 Rockstar 2FA 的钓鱼即服务(PhaaS)工具包遭遇变故,意外推动了另一个新生服务 Flo…...

玩转OCR | 探索腾讯云智能结构化识别新境界
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀ 玩转OCR 腾讯云智能结构化识别产品介绍服务应用产品特征行业案例总结 腾讯云智能结构化识别 腾讯云智能结构化OCR产品分为基础版与高级版&am…...

idea2024创建JavaWeb项目以及配置Tomcat详解
今天呢,博主的学习进度也是步入了JavaWeb,目前正在逐步杨帆旗航,迎接全新的狂潮海浪。 那么接下来就给大家出一期有关JavaWeb的配置教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正…...

外连接转AntiJoin的应用场景与限制条件 | OceanBase SQL 查询改写系列
在《SQL 改写系列:外连接转内连接的常见场景与错误》一文中,我们了解到谓词条件可以过滤掉连接结果中的 null 情形的,将外连接转化为内连接的做法是可行的,正如图1中路径(a)所示。此时,敏锐的你或许会进一步思考&#…...

华为实训课笔记 2024 1223-1224
华为实训 12/2312/24 12/23 [Huawei]stp enable --开启STP display stp brief --查询STP MSTID Port Role STP State Protection 实例ID 端口 端口角色 端口状态 是否开启保护[Huawei]display stp vlan xxxx --查询制定vlan的生成树计算结…...

MySQL超详细安装配置教程(亲测有效)
目录 1.下载mysql 2.环境配置 3.安装mysql 4.navicat工具下载与连接 5总结 1.下载mysql mysql下载--MySQL :: 下载 MySQL 社区服务器 下载的时候这里直接逃过就行 我这里的版本是最新的mysql8.0.37 下载完成之后,将压缩包进行解压 这里我建议大…...

MySQL 8.0:explain analyze 分析 SQL 执行过程
介绍 MySQL 8.0.16 引入一个实验特性:explain formattree ,树状的输出执行过程,以及预估成本和预估返 回行数。在 MySQL 8.0.18 又引入了 EXPLAIN ANALYZE,在 formattree 基础上,使用时,会执行 SQL &#…...
信管通低代码信息管理系统应用平台
目前,国家统一要求事业单位的电脑都要进行国产化替代,替代后使用的操作系统都是基于linux的,所有以前在WINDOWS下运行的系统都不能使用了,再者,各单位的软件都很零散,没有统一起来。需要把日常办公相关的软…...

git推送本地仓库到远程(Gitee)
目录 一、注册创建库 二、创建仓库 三、推送本地仓库到远程 1.修改本地仓库用户名和邮箱 2.本地库关联远程仓库 3.拉取远程仓库的文件 4.推送本地库的文件 5.查看远程仓库 四、远程分支查看 1.查看远程分支 2.修改test.txt文件 一、注册创建库 Gitee官网࿱…...

【C++语言】多态
一、多态的概念 多态的概念:通俗来说,就是多种形态,具体点就是去完成某种行为,当不同的对象去完成时会产生出不同的状态。 我们可以举一个例子: 比如买票这种行为,当普通人买票时,是全价买票&am…...
ThinkPHP 吸收了Java Spring框架一些特性
ThinkPHP 吸收了Java Spring框架一些特性,下面介绍如下: 1、controller 控制器层 存放控制器层的文件,用于处理请求和响应 2、model 实体类 存放实体类的文件,用于定义数据模型 3、dao DAO层 存放DAO(数据访问…...

自动控制系统综合与LabVIEW实现
自动控制系统综合是为了优化系统性能,确保其可靠性、稳定性和灵活性。常用方法包括动态性能优化、稳态误差分析、鲁棒性设计等。结合LabVIEW,可以通过图形化编程、高效数据采集与处理来实现系统综合。本文将阐述具体方法,并结合硬件选型提供实…...

记录一个SVR学习
1、为什么使用jupter来做数据预测?而不是传统pycharm编辑器 1、Jupyter Notebook 通过anaconda统一管理环境,可以运行python、R、Sql等数据分析常用语言。 2、做到交互式运行,可以逐步运行代码块,实时查看结果,便于调…...
Java内存区域进一步详解
方法区 方法区属于是 JVM 运行时数据区域的一块逻辑区域,是各个线程共享的内存区域。 《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用,方法区到底要如何实现那就是虚拟机自己要考虑的事情了。也就是说,在不同的虚拟机实现上&am…...

SpiderFlow平台v0.5.0流程的执行过程
流程执行过程: 1. 流程启动 流程的执行通常从一个 开始节点 开始,该节点是整个爬虫任务的起点。开始节点没有实际的功能作用,主要作用是标记流程的起始。 执行顺序:在执行过程中,系统按照流程中的连接线顺序依次执行…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...