网络编程,端口号,网络字节序,udp
前面一篇我们讲了网络的基础,网络协议栈是什么样的,数据如何流动传输的;接下来这篇,我们将进行实践操作,真正的让数据跨网络进行传输;
1.网络编程储备知识
1.1 初步认识网络编程
首先我们需要知道我们的网络编程实例化到现实生活中就是使用app进行交互,这样的交互其实就是两台不同机器上的进程在进行通信,这其实也叫做进程间通信,不过是通过网络来进行的罢了;此时两个进程的共享内存叫做网络;
1.网络协议栈的下三层主要是用来保证数据的安全传输的问题
2.我们编程主要编写的是应用层代码
3.用户通过使用我们编写好的程序来进行数据发送与接收
1.2 端口号
认识端口号
我们编写的应用层代码形成程序载入内存时成为进程需要被标识,让网络可以通过IP找到机器通过标识找到当前进程,而这个标识就叫做——端口号;
1.端口号是一个2字节16比特位的整数
2.可以使用端口号找到机器上唯一进程
3.一个端口号只能对应一个进程(但一个进程可以有多个端口号)
端口号与pid
在我们前面linux系统的学习中,我们知道进程都有自己唯一的pid,那为什么我们不直接使用pid来标识进程呢,为什么还要引出一个端口号?
因为端口号是属于网络体系的,而pid是属于系统体系的,如果将pid直接作为端口号来标识唯一进程也是可以的,可是这样会存在一些问题:
1.pid是随机变化的,每次进程启动是pid都会发生改变,有些端口号是固定不变的
2.当系统中的pid需要调整时会导致网络中的端口号也随之改变,会增加维护的难度
3.高内聚,低耦合的思想
端口号绑定进程
我们如何理解将端口号绑定到一个进程上?
我们可以看作端口号与进程的pcb指针形成了hash键值对,从而可以通过端口号找到相应的进程;
1.3 网络字节序
世界上的机器是无穷多的,所以设备是个性化的,机器的实现一定是具有差异的,但是为了让机器可以正常通信,要使用网络覆盖底层的实现,让上层的交互规则是一样的;网络字节序就是这样一种覆盖的方式,我们的机器是存在大小端之分的,数据的传输也会存在数据的发送顺序问题,为了解决不同机器数据传输顺序的问题,需要使用网络下的函数,让传输进入网络中的数据按照网络字节序的形式存在;
只要是要传输到网络中的数据都要使用下面的函数对数据进行转换:
记忆方法:h为host(主机),n为network,l为长整型32位,s位短整型16位
htons就是将16位短整型数据由主机字节序转换为网络字节序;
ntohs就是将16位短整型数据由网络字节序转换为主机字节序;
1.4 初步认识tcp与udp
tcp
理解为打电话形式,数据是一定准确的传输到对方的
1.传输可靠(中性词,可靠但复杂)
2.有连接
3.面向字节流传输
udp
理解为发电报模式,我们不清楚我们的数据是否成功送达
1.传输不可靠(中性词,不可靠但简单)
2.无连接
3.面向数据报传输
1.5 socket套接字接口
套接字我们可以理解为底层开放给我们的接口,我们可以通过这个接口将数据送入底层进行传输;下面是socket套接字的接口:
1.创建socket套接字(我们可以理解为打开底层的网卡文件)
2.绑定套接字与端口号(也就是将进程和网卡连接起来,让进程可以向网卡发送数据)
3.udp接收数据报接口
4.udp发送数据报接口
2.实现upd客户端服务器通信
接下来我们通过实践来学习网络编程:
下面是我编写好的一份udp客户端与服务端通信的代码:
network_code/socket_2024_9_17 · future/Linux - 码云 - 开源中国 (gitee.com)
我们使用udp模拟的现象是两个进程可以通过网络进行通信;
下面是对代码关键地方的讲解:
2.1 socket与bind
首先,进程如果想通过网络进行交互,那么肯定需要先连接网络;那么如何连接呢,我们需要使用socket和bind函数;
2.1.1 socket
socket的头文件是<sys/types.h>与<sys/socket.h>
socket的第一个参数用来指定套接字是在哪个域中属于协议家族中的哪个协议,man手册中展示了有这些协议:
socket的第二个参数是指定套接字的数据类型 ,指定通信语义,其中sock_stream是面向字节流的数据类型,sock_dgram是面向数据报的数据类型
最后一个参数一般设置为0即可,可以自动绑定协议,我们也可以显示的设置
socket函数的返回值是一个文件描述符,这个文件描述符指向的是我们的网卡文件(linux下一切皆文件),当返回值为-1时代表打开socket失败并会设置errno错误码;
2.1.2 bind
我们通过上一步创建了套接字后,我们接下来就要将进程绑定上套接字,使得可以让网络找到当前进程;
bind函数的返回值成功绑定返回0失败返回-1并设置errno错误码,第一个参数是通过socket函数打开的网卡文件的文件描述符,第二参数是一个结构体的指针,第三个参数是这个结构体的大小;这个结构体指针是一个结构类型,可以用来接收两种不同类型的结构体;
2.1.3 sockaddr
这是bind函数的第二个参数的结构体类型,这个类型作为指针时可以接收两种不同结构体:
这样bind就可以通过一个参数接收不同类型的数据了;
我们在真正编程的时候是需要设置好sockaddr_in的各个成员变量的:
struct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_addr.s_addr = inet_addr(_ip.c_str());local.sin_port = htons(_port);
上面的代码中我们一个个的设置好了上面各个参数的值,这些值因为要输入网络中,所以都需要是网络字节序,我们要使用htons函数与inet_addr来操作修改为网络字节序;其中htons的头文件是<arpa/inet.h>,inet_addr的头文件是<netinet/in.h>和<arpa/inet.h>;
我们设置好变量后通过bind函数进行绑定即可;
2.2 recvfrom与sendto
我们打开socket并绑定bind好后,就可以向网络中发送数据了,由于我们现在使用的是udp协议的网络编程,我们使用recvfrom与sendto来进行数据接收与发送;
实现示例:
char buffer[1024];
struct sockaddr_in client;
socklen_t len = sizeof(client);int n = recvfrom(_fd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&client, &len);
if (n == -1)
{log(WARNING, "recvfrom fail!");
}
buffer[n] = '\0';
将从网络中接收到的数据放入buffer中;
实现示例:
string info = "get message: ";
info += buffer;n = sendto(_fd, info.c_str(), info.size(), 0, (const struct sockaddr *)&client, len);
if (n == -1)
{log(WARNING, "sendto fail!");
}
2.3 网络状态查看指令
netstat -naup(-nlup)
2.4 IP地址绑定细节
进程在绑定自己的ip地址时一般是不需要自己进行绑定的,我们设置绑定ip地址为0.0.0.0即可
原因:
1.云服务器上的ip地址是虚拟地址,无法绑定虚拟ip
2.一台主机可以有多张网卡,当我们显示绑定其中一张的ip时其他ip的信息我们无法收到,所以我们直接设置为0可以接收所有发送到本机ip上的信息
所以我们可以这样绑定ip地址:
sin_addr.s_addr=htonl(INADDR_ANY);
INADDR_ANY这个宏在底层定义的也是0.0.0.0地址
2.5 端口号绑定细节
对于用户端,绑定端口号时我们不需要显示绑定,当客户端进程,开始发送消息时,系统会帮进程自动绑定本地的某个端口号与本地IP地址;
原因:
1.用户使用的客户端是不同厂家写的,不同厂家在写程序时如果显式的绑定了端口号,无法预测会不会和用户机器上其他的进程冲突,所以会将绑定端口号的操作交给用户机器的操作系统;
2.端口号对于用户来说并不重要,只需要让端口号识别唯一进程即可;
2.6 用户如何知道服务端端口号与ip地址
其实端口号和地址可以看作我们平时上网用的网站,网站的字符串可以被解析为IP地址与端口号,而浏览器就是通过这个ip地址与端口号找到相应服务器的;而服务器的厂商会通过宣传让人们知道它网站的域名;
2.8 云服务器防火墙
在我们使用云服务器时,我们是无法做到网络连接的,因为我们本主机上的端口号为了安全是被云服务器厂商设置了防火墙的,目的就是为了防止有人通过外部设备访问云服务器主机上的进程;而我们想要进行网络通信就必须得开放这个端口,我的腾讯云服务器是在控制台的防火墙处进行配置,要先配置好端口号才可以让其他进程通过网络连接云服务器上进程;如果你也遇到了明明编写好了程序可是就是无法进行网络交互,你试着把IP地址改为127.0.0.1这是本地环回地址,可以连接本地的网络,如果这样成功了就代表是你的防火墙拦住了你,你去设置一下即可;
2.9 实现的现象
3.udp服务器和客户端升级
3.1 服务器端接收数据处理的封装
上面我们实现了基础的udp客户端和服务器,接下来,我们可以将服务器的功能进行封装,使其成为回调函数,让服务器中的main函数,通过参数传递给服务器类,从而实现一个执行命令,和通信的功能:
network_code/socket_2024_9_17/2_udp_pro · future/Linux - 码云 - 开源中国 (gitee.com)
上面的代码相比与最前面的代码仅仅只是对处理客户端发送来的数据进行了封装,模拟处来了现实生活中,客户端对服务器发送请求,服务器接收请求后对请求进行处理,随后再返回给客户端的情况:
下面是实现的情况:
#include"server.hpp"string addStr(const string& buffer)
{string info = "get message: ";info += buffer;cout << info << endl;return info;
}bool checksafe(const string& comd)
{vector<string> v={"rm"};for(auto word:v){if(comd.find(word)!=string::npos){return true;}}return false;
}string command(const string& comd)
{cout<<comd<<endl;if(checksafe(comd)){return "command not safe";}FILE*f=popen(comd.c_str(),"r");if(f==nullptr){cout<<strerror(errno)<<endl;exit(-1);}string back_info;while(true){char buffer[4096]={0};char * ret=fgets(buffer,sizeof(buffer),f);if(ret==nullptr)break;back_info+=buffer;}return back_info;
}int main(int argc, char *argv[])
{if (argc != 2){log(ERROR,"argc should be 2");exit(-1);}uint16_t port=stoi(argv[1]);unique_ptr<udpserver> ptr(new udpserver(port));ptr->run(addStr);return 0;
}
通过将函数方法传递实现了对数据的不同方式的处理,上面的addStr和command两个函数就是我们封装好的方法可以通过将这个两个方法进行传递从而,从而改变,服务端对数据的处理,其实在未来的工作中,我们的代码一般都是合作交互的,所以我们设计一个这样的接口交给其他人时,就可以减少耦合度,其他人只需要编写他们想要的接口,不会和我们的代码产生修改的矛盾;
3.2 windows下udp客户端实现
其实这并没有难度,代码实现是与我们linux客户端一样的只不过,我们需要注意windows下的库是如何处理的,我们需要将windows下的网络库先初始化,之后方才可以进行访问,使用库的功能,下面是windows下udp客户端的实现:
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1#include <WinSock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
#include<string>
#include <windows.h> // 用于字符编码转换
using namespace std;// 将 GBK 编码转换为 UTF-8
string GbkToUtf8(const string& gbkStr)
{int len = MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), (int)gbkStr.length(), NULL, 0);wchar_t* wstr = new wchar_t[len + 1];MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), (int)gbkStr.length(), wstr, len);wstr[len] = '\0';len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);char* str = new char[len + 1];WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);str[len] = '\0';string utf8Str(str);delete[] wstr;delete[] str;return utf8Str;
}// 将 UTF-8 编码转换为 GBK
string Utf8ToGbk(const string& utf8Str)
{int len = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0);wchar_t* wstr = new wchar_t[len + 1];MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, wstr, len);wstr[len] = '\0';len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);char* str = new char[len + 1];WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);str[len] = '\0';string gbkStr(str);delete[] wstr;delete[] str;return gbkStr;
}int main()
{// 初始化套接字库WORD mVersion;WSADATA wsaData;int err;mVersion = MAKEWORD(1, 1);err = WSAStartup(mVersion, &wsaData);if (err != 0){return err;}// 创建 UDP 套接字SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr("111.229.31.168"); // 服务器 IP 地址addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(10000); // 服务器端口SOCKADDR_IN addrCli;int len = sizeof(SOCKADDR);while (true){cout << "请输入:";string sendBuf;getline(cin, sendBuf);string sendMsg = GbkToUtf8(sendBuf);char recvBuf[100] = { 0 };// 发送数据到服务器sendto(sockCli, sendMsg.c_str(), sendMsg.size(), 0, (SOCKADDR*)&addrSrv, len);// 接收服务器发送的数据recvfrom(sockCli, recvBuf, sizeof(recvBuf)-1, 0, (SOCKADDR*)&addrCli, &len);string recvMsg = Utf8ToGbk(recvBuf);cout << recvMsg << endl;}// 关闭套接字并清理库closesocket(sockCli);WSACleanup();return 0;
}
未来防止windows上编译器编码格式和linux客户端的不同,我们对数据进行了处理,使得windows客户端上发送的信息发送到服务器上不会变成乱码,我们还加入了两个编码转换函数,当然这两个编码转换函数的实现不是我自己实现的,因为windows下的底层编码,我没有怎么学过;但我知道有编码转换的问题,我通过使用gpt找到编码转换的函数,载入我的代码中,成功的实现了windows和linux下进程的交互工作,下面是实现的现象:
从而,我们也可以理解,我们为什么在linux操作环境下编写代码部署到linux机器上,而大多数使用windows机器的人也都可以享受linux服务器的服务,这便是网络带来的便利;
3.3 服务器与客户端改造形成聊天室
接下来,我们将服务器再改造一下,使其可以将一个客户端发送的数据进行处理后发送给所有的客户端,使得可以形成一个群聊的模式;
network_code/socket_2024_9_17/3_udp_chatRoom · future/Linux - 码云 - 开源中国 (gitee.com)
上面是我代码的完整实现;
其中主要有这几个功能:
1.我们要识别每个不同的机器
2.我们要将接收的信息转发给每个连接了服务器的客户端
3.客户端接收信息和发送信息是并发的
解决方式:
1.将接收到的客户端套接字信息sockaddr中的port和ip获取出来,标识每个不同机器
2.通过存入不同机器的sockaddr和ip信息来分别发送给每个不同的机器
3.通过多线程的方式让客户端的接收和发送功能同时运行
下面是实现的现象:
本篇我们实现了udp客户端和服务器的功能下一篇我们将实现tcp服务器;
3.4 补充
补充俩个指令:
sz(文件名) 发送数据到本地主机
rz 从本地主机上获取数据
对网络字节序转换函数的提醒:
我们在转换ip地址时,有可能需要将网络字节序转回本机,我们可以使用:
inet_ntoa(可能存在线程问题)
inet_ntop(使用是安全的)
相关文章:

网络编程,端口号,网络字节序,udp
前面一篇我们讲了网络的基础,网络协议栈是什么样的,数据如何流动传输的;接下来这篇,我们将进行实践操作,真正的让数据跨网络进行传输; 1.网络编程储备知识 1.1 初步认识网络编程 首先我们需要知道我们的…...

Android入门
下载Android studio,创建第一个项目 模板可以选择empty views Activity 在这个界面可以修改,使用语言,项目名字,存储路径以及适用版本 完成后,得到一个最初始的Android 项目,红色标记的两个文件…...

二叉树深搜专题篇
目录 计算布尔二叉树的值 求根节点到叶节点数字之和 二叉树剪枝 验证二叉搜索树 二叉搜索树中第K小的元素 二叉树的所有路径 计算布尔二叉树的值 题目 思路 这道题其实是比较简单的,对二叉树来一次后序遍历即可,当遇到叶子结点直接返回叶子节点中…...

堆【数据结构C语言版】【 详解】
目录-笔记整理 一、思考二、堆概念与性质三、堆的构建、删除、添加1. 构建2. 删除3. 添加 四、复杂度分析4.1 时间复杂度4.2 空间复杂度 五、总结 一、思考 设计一种数据结构,来存放整数,要求三个接口: 1)获取序列中的最值&#…...

初识React
在最新写需求的时候,我遇到了一个需求,这个需求改后端改的不算多,而且也比较简单,但是在改前端的时候,很复杂。因为我们这个项目用的是React做前端的,而我对于前端知识没有了解,所以理解很多代码…...

VUE 开发——AJAX学习(三)
一、async函数和await async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用Promise async写在函数声明的前面;在async函数内,使用await关键字,获取Promise对象“成功状态”结果值 &…...

C++杂项
作业: 将之前实现的顺序表、栈、队列都更改成模板类 顺序表 #include <iostream>using namespace std;template<typename T>class SeqList { private:T *ptr;int size; //总长度int len 0; //当前顺序表实际长度public://初始…...

Gelatinous Cube Sphere - Bonus Files 2 - Atavism
这是Gelatinous Cube & Sphere Pack的奖励文件包。 奖励文件: ⭐ 概念艺术 也可在Monster Bundle #2中使用。 下载:Unity资源商店链接资源下载链接...

锐捷—NAT地址映射+IPsec隧道
任务目标 在出口路由器R3上将R5私网地址1对1映射的公网地址与R1建立IPsec隧道,使得R4在访问R5的映射公网地址时,可以进行IPsec隧道的转发 要求: 1、R4和R5可通过NAT转换正常访问互联网地址(R2的lo0) 2、R5的私网地…...
index.html 调用 ajax
index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>AJAX 请求示例</title><script>// 封装 Ajax 为公共函数:传入回调函数 success 和 failfunction myAjax (url, suc…...

uniapp学习(003-1 vue3学习 Part.1)
零基础入门uniapp Vue3组合式API版本到咸虾米壁纸项目实战,开发打包微信小程序、抖音小程序、H5、安卓APP客户端等 总时长 23:40:00 共116P 此文章包含第11p-第p14的内容 文章目录 vue3使用介绍插值表达式例子时间戳随机数输出函数的值 ref响应式数据变量v-bind 绑…...

计算机毕业设计 基于深度学习的短视频内容理解与推荐系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
JavaScript网页设计案例深度解析:从理论到实践
前言 在现代前端开发中,JavaScript 是赋予网页生命的关键技术。静态的 HTML 和 CSS 虽然能创建美观的页面,但当我们需要增强用户交互和页面响应时,JavaScript 无疑成为最得力的工具。从程序员的角度来看,JavaScript 设计不仅仅是…...

spark-sql建表数据同步到hive
1、基础环境 组件版本备注hadoop3.4.0官方下载hive3.1.3自编译sparkspark-3.5.3-bin-hadoop3官方下载,需要内置hive的jar相关内容paimon0.9.0Maven官方下载jdk1.8.0_41maven3.9.6固定版本 2、停止服务、清理日志 先停止,清理数据 sudo kill -9 $(ps -ef…...
Django上下文处理器
1创建 (如frontend目录下)category_processors文件: def categories(request):from backend.models import Categorycategory_list Category.objects.all()return {category_list:category_list}这里,必须返回一个字典。 2&…...

旭升集团携手纷享销客,构建全方位客户关系管理平台
宁波旭升集团股份有限公司(以下简称“旭升集团”)自2003年成立,总部位于中国宁波,集团设有压铸、锻造、挤压、集成四大事业部,在亚洲、欧洲、美洲等地均设立研发中心及制造基地,产品主要覆盖新能源汽车的电…...

uniapp 知识点
自定义导航 在page.json navigationstyle":"custom"navigateTo传参 页面传参只能onLoad(option)里面拿 px和upx的关系 在750设计图中,1px1upx 路由 navigateBack返回上一页 重定向 其实就是把当前页面干掉了 公共组件和页面共同点 computed,watc…...

慢病中医药膳养生食疗管理微信小程序、基于微信小程序的慢病中医药膳养生食疗管理系统设计与实现、中医药膳养生食疗管理微信小程序的开发与应用(源码+文档+定制)
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
解决 Android WebView 无法加载 H5 页面常见问题的实用指南
目录 1. WebView 简介 2. 常见问题 3. 网络权限设置 4. 启用 JavaScript 5. DOM Storage 的重要性 6. 处理 HTTPS 问题 7. 设置 WebViewClient 8. 调试工具 9. 其他调试技巧 10. 结论 相关推荐 1. WebView 简介 Android WebView 是一种视图组件,使得 And…...

Ollama本地部署大模型及应用
文章目录 前言一、下载安装1.Mac2.Windows3.linux4.docker5.修改配置(可选)1.linux系统2.window 系统3.mac系统 二、Ollama使用1.命令2.模型下载3.自定义模型4.API 服务 三、Open WebUI 使用四、Dify使用 前言 Ollama 是一个专注于本地部署大型语言模型…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...