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

网络的历史及socket接口了解

一、网络发展历史这一部分只是了解一下即可在最开始每一台计算机都是独立的计算机如果我们两个人需要协同作业都需要一个人先做一部分然后拷贝下来到另外一台主机上交由另外一个人来继续完成。但是这样效率就比较低下于是人们直接将多个计算机用数据线连接到一起就可以随心所欲的进行数据的传输。随着计算机的发展计算机的数量越来越多更多的计算机需要进行通信我们计算机想和别人进行通信需要在身上开一个网口直接用线连接但是那么多的计算机所需要开的网口数量也是呈几何式进行增长的。于是有人发明了集线器。这是一个纯粹属于物理层的机器。你们将自己的网线连接到一个公共的地方---集线器他仅仅是无脑将电信号向每一个端口转发的一个物理设备。但由于他转发给了所有的端口不同的计算机如何知道这个数据是给我来使用的呢首先我们需要给每一个计算机都起一个名字比如ABCD他是一个全局唯一的标识。但是为了高端一点我们把这个名字叫做MAC地址。比如你的mac地址是aaaaaaaa你要连接的计算机的mac地址是bbbbbbbb那么我们只需要在所发送数据的前面拼接一个“快递单”这个我们称为报头上面填写了发件人源mac地址和收件人目标mac地址。集线器还是转发给每一个人但是我们收到数据后拿出来一看这个数据的目标mac地址不是我那我就直接丢弃如果是我的我把快递单拆下来拿出里面的数据包再来使用。这样的模型相比之前需要把每一台机器都连接起来倒是方便了不少但是也出现了一个问题原来我只需要1v1的发送现在却需要给所有机器都发送一遍更麻烦的是即使不是我的数据我也要先拿来看看再丢弃这样就造成了网络资源的浪费。于是出现了交换机。交换机相比于集线器升级了一点他不需要向每一个机器都广播数据了而是自己内部有一张mac地址和端口对应的表在发送数据前会先去看看我的目标mac对应的是哪一个端口然后指定性的向该端口发送数据。我们把这样基于交换机形成的小范围网络称为现代以太网以前的集线器模式也称以太网。当计算机的数量再次变多的时候我们只需要用多个交换机相连接经过多次跳转就能找到目标机器。像这样A机器想向H发送首先在自己直连的交换机中查找发现是6号端口于是向6号端口发送数据就到了第二个交换机第二个交换机把你的报头拿出来一看哦他的目标mac是H机器然后再查表发现是6号端口再向该端口发送数据就实现了A向H的数据传输。但是计算机这个时候再一次爆炸发展数量完全不是几个交换机能满足的了。你发现问题的关键在于交换机之间互联的那根线不知道是级联了多少个交换机每一台交换机上都需要存储所有的机器的地址表要知道每条机器的路径才能不断通过交换机来实现数据的跳转这使得地址表越来越大。然后人们就发明了一个东西----路由器。路由器把不同的交换机又连接起来他和我们的电脑一样有着自己的mac地址但是路由器还有一个功能就是可以帮我把数据做一次转发现在我们交换机所需要记录的mac表负担就很小了他不再需要把每一台机器的mac地址都记住而是只用记录和自己直连的机器的mac以及自己连接的路由器的mac在a向b发送消息的时候直接通过交换机就发送了如果a向c发送会先通过交换机交换机一看这不属于我的子网范围我直接交由路由器去处理。但是路由器同样不可能做到完整记录所有的MAC、端口映射表否则就和刚刚的交换机困境没区别了所以路由器的做法是让同一个子网下拥有类似的前缀地址只用区分后面几位不同即可。假如C和D有着同样的mac前缀XXXX-XXXX-不同的部分。如果我们想让某个数据同时发送给C和D就先把数据交给路由器然后路由器通过前缀来判断需要发送给哪一个端口的交换机然后再由交换机进入子网进行传输。但是如果C和D是由不同的厂家生产的他们的mac地址之前没有相似性即mac的前半部分完全不一样这个时候路由器就犯傻了他俩的前缀不在一个端口咋办呀但是他们又在同一个子网经过同一个交换机难道一个交换机需要连好多根线到一个路由器上的不同端口吗又或者路由器需要把下游的机器的mac地址全部记住吗这显然是不合理的。于是我们又设计了一种新的地址---IP地址。他是一个32位的二进制编号我们通常把他按每8位分开比如127.255.128.0这个我们称为点分十进制的描述方法。然后命名为IP地址。不同厂家生产的机器虽然mac地址不同但是我们却可以再软件层面上让他们的IP地址的前缀相同这样路由器就可以通过这个相同的前缀把数据发送到某个特定的交换机上了。现在由于路由器的产生我们又需要增加一个报头---网络层头部。我们来分析看看机器A想把数据发送给机器C先在数据链路层交换机层解开数据链路的头部发现源mac和目标mac不是都连在我这个交换机上的不在一个子网那么我就把解开的头部再放回去并修改一下源mac和目标mac然后交给路由器路由器这次要拆开网络层头部一看源IP和目标IP都在我这个路由器的管束的范围内如果不在就封装回去修改数据链路头部发送给在一个路由器我就把网络层丢掉修改一下数据链路层头部告诉交换机我要去哪个mac地址然后由交换机再来拆开一看目标mac刚好就在我这里直连了我就把数据链路头部丢掉把数据包发给目标机器。这样就完成了数据的发送。二、socket编程的函数接口1格式化API2sockaddr结构socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及后面要讲的UNIX DomainSocket. 然而, 各种网络协议的地址格式并不相同.三、实现Udp通信1基础通信版udp_server.cc#includeiostream #includememory #includestring #includecstring #includecerrno #includestrings.h #includeunistd.h #include sys/socket.h #include sys/types.h #include netinet/in.h #includearpa/inet.h #includeComm.hpp #includenocopy.hpp #includeLog.hpp #includeinetAddr.hpp const static std::string default_ip0.0.0.0; const static uint16_t default_port8888; class Udp_server:public nocopy { public: // Udp_server(const std::string ipdefault_ip,uint16_t portdefault_port); Udp_server(uint16_t portdefault_port); ~Udp_server(); void Init(); void Start(); private: //std::string _ip;//不需要ip地址了 uint16_t _port; int _sockfd-1; }; // Udp_server::Udp_server(const std::string ip,uint16_t port) Udp_server::Udp_server(uint16_t port) :_port(port) { } Udp_server::~Udp_server() { } void Udp_server::Init() { //创建套接字 _sockfd socket(AF_INET,SOCK_DGRAM,0); if(_sockfd0) { lg.LogMessage(Fatal,socket创建失败,%d:%s\n,errno,strerror(errno)); exit(Socket_Err); } lg.LogMessage(Info,socket创建成功,sockfd:%d\n,_sockfd); //绑定 struct sockaddr_in local; bzero(local,sizeof(local));//把local清空 local.sin_familyAF_INET; local.sin_porthtons(_port);//htons是主机序列转网络序列 //不要将ip地址绑定不绑定就能接受本机上所有网卡的信息绑定了只能接受一个网卡的信息 local.sin_addr.s_addrINADDR_ANY; //local.sin_addr.s_addrinet_addr(_ip.c_str());//将char*类型转换成网络地址 int retbind(_sockfd,(struct sockaddr*)local,sizeof(local)); if(ret-1) { lg.LogMessage(Fatal,套接字绑定失败,%d:%s\n,errno,strerror(errno)); exit(Bind_Err); } lg.LogMessage(Info,套接字绑定成功\n); } void Udp_server::Start() { //服务器运行起来后永远不退出 while(1) { char buffer[1024]; struct sockaddr_in peer; socklen_t lensizeof(peer); //接收客户端的消息 //返回值是实际收到的字节数参数是期望收到的字节数 ssize_t retrecvfrom(_sockfd,buffer, sizeof(buffer)-1,0,(struct sockaddr*)peer,len); if(ret0) { //获取客户端的ip地址和端口号 InetAddr addr(peer); buffer[ret]0; std::cout[addr.Print_Debug()]说:bufferstd::endl; ssize_t nsendto(_sockfd,buffer,strlen(buffer),0,(struct sockaddr*)peer,len); if(n-1) { lg.LogMessage(Info,服务器回复消息失败,%d:%s,errno,strerror(errno)); } } } } void Usage(std::string proc) { std::coutUsage:\n\tproc local_Port\nstd::endl; } int main(int argc,char* argv[]) { if(argc!2) { Usage(argv[0]); return Usage_Err; } //记录输入的ip和port // std::string ipargv[1]; uint16_t portstd::stoi(argv[1]); //创建Udp_server对象 // std::unique_ptrUdp_server userstd::make_uniqueUdp_server(ip,port); // std::unique_ptrUdp_server userstd::unique_ptrUdp_server(new Udp_server(ip,port)); std::unique_ptrUdp_server userstd::unique_ptrUdp_server(new Udp_server(port)); user-Init(); user-Start(); return 0; }udp_client.cc#includeiostream #includestring #includecerrno #includecstring #includeunistd.h #include sys/socket.h #include sys/types.h #include netinet/in.h #includearpa/inet.h #includeLog.hpp void Usage(const std::string process) { std::coutUsage:\n\tprocess server_ip server_portstd::endl; } int main(int argc,char* argv[]) { if(argc!3) { Usage(argv[0]); return 2; } //获取服务器的端口号和ip地址 std::string server_ipargv[1]; uint16_t server_portstd::stoi(argv[2]); //创建套接字 int socksocket(AF_INET,SOCK_DGRAM,0); if(sock0) { std::cerrsocket创建失败:strerror(errno)std::endl; return 1; } std::cout创建套接字成功sockstd::endl; //绑定套接字(客户端不用绑定因为同时可以有多个客户端发消息所以代码不能写死在sendto的时候自动就绑定了) //一旦绑定了这个app的客户端就占用了一个端口但是市面上有那么多的端口显然不能都满足于是让操作系统自动选择绑定的端口 //服务器的信息 struct sockaddr_in server; bzero(server,sizeof(server));//把local清空 server.sin_familyAF_INET; server.sin_porthtons(server_port);//htons是主机序列转网络序列 server.sin_addr.s_addrinet_addr(server_ip.c_str());//将char*类型转换成网络地址 socklen_t lensizeof(server); //客户端一直发送数据 while(1) { std::string inbuffer; std::cout请输入std::endl; getline(std::cin,inbuffer); ssize_t nsendto(sock,inbuffer.c_str(),inbuffer.size(),0,(struct sockaddr*)server,len); if(n0) { char buffer[1024]; struct sockaddr_in temp; socklen_t len2sizeof(temp); ssize_t mrecvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)temp,len2); if(m0) { buffer[m]0; std::cout服务器回复:bufferstd::endl; } else { break; } } else { break; } } close(sock); return 0; }inetAddr.hpp#pragma once #includeunistd.h #include sys/socket.h #include sys/types.h #include netinet/in.h #includearpa/inet.h #includestring #includeiostream //这是一个获取对方的ip地址和端口号的对象会返回一个string来表示他们 class InetAddr { public: InetAddr(struct sockaddr_in addr) :_addr(addr) { //记录客户端的ip地址和端口号 _portntohs(_addr.sin_port); _ipinet_ntoa(_addr.sin_addr); } ~InetAddr(){} std::string IP() { return _ip; } uint16_t Port() { return _port; } std::string Print_Debug() { std::string info_ip; info:; infostd::to_string(_port); return info; } private: std::string _ip; uint16_t _port; struct sockaddr_in _addr; };comm.hpp#pragma once enum { Usage_Err1, Socket_Err, Bind_Err, };nocopy.hpp#pragma once #includeiostream //这个类的拷贝构造和赋值重载被禁用了所以继承了他的子类只能调用构造函数而不能使用拷贝构造和赋值重载 //由于我们使用了unique_ptr来管理该子类所以该子类只能存在一份 class nocopy { public: nocopy(){}; ~nocopy(){}; nocopy(const nocopy )delete; const nocopy operator(const nocopy)delete; };(2)利用popen实现进程替换执行命令行udp_server.cc#includeiostream #includestdio.h #includememory #includestring #includecstring #includecerrno #includestrings.h #includeunistd.h #include sys/socket.h #include sys/types.h #include netinet/in.h #includearpa/inet.h #includefunctional #includeComm.hpp #includenocopy.hpp #includeLog.hpp #includeinetAddr.hpp const static std::string default_ip0.0.0.0; const static uint16_t default_port8888; //函数类型 using func_tstd::functionstd::string(std::string); class Udp_server:public nocopy { public: // Udp_server(const std::string ipdefault_ip,uint16_t portdefault_port); Udp_server(func_t onMessage,uint16_t portdefault_port); ~Udp_server(); void Init(); void Start(); private: //std::string _ip;//不需要ip地址了 uint16_t _port; int _sockfd-1; func_t _onMessage;//回调函数 }; // Udp_server::Udp_server(const std::string ip,uint16_t port) Udp_server::Udp_server(func_t onMessage,uint16_t port) :_onMessage(onMessage),_port(port) { } Udp_server::~Udp_server() { } void Udp_server::Init() { //创建套接字 _sockfd socket(AF_INET,SOCK_DGRAM,0); if(_sockfd0) { lg.LogMessage(Fatal,socket创建失败,%d:%s\n,errno,strerror(errno)); exit(Socket_Err); } lg.LogMessage(Info,socket创建成功,sockfd:%d\n,_sockfd); //绑定 struct sockaddr_in local; bzero(local,sizeof(local));//把local清空 local.sin_familyAF_INET; local.sin_porthtons(_port);//htons是主机序列转网络序列 //不要将ip地址绑定不绑定就能接受本机上所有网卡的信息绑定了只能接受一个网卡的信息 local.sin_addr.s_addrINADDR_ANY; //local.sin_addr.s_addrinet_addr(_ip.c_str());//将char*类型转换成网络地址 int retbind(_sockfd,(struct sockaddr*)local,sizeof(local)); if(ret-1) { lg.LogMessage(Fatal,套接字绑定失败,%d:%s\n,errno,strerror(errno)); exit(Bind_Err); } lg.LogMessage(Info,套接字绑定成功\n); } void Udp_server::Start() { //服务器运行起来后永远不退出 while(1) { char buffer[1024]; struct sockaddr_in peer; socklen_t lensizeof(peer); //接收客户端的消息 //返回值是实际收到的字节数参数是期望收到的字节数 ssize_t retrecvfrom(_sockfd,buffer, sizeof(buffer)-1,0,(struct sockaddr*)peer,len); if(ret0) { //获取客户端的ip地址和端口号 InetAddr addr(peer); //收到的消息存储在buffer中 buffer[ret]0; //用回调函数去处理收到的消息 std::string response_onMessage(buffer); std::cout[addr.Print_Debug()]发送了请求:bufferstd::endl; //处理完成把结果返还回去 ssize_t nsendto(_sockfd,response.c_str(),response.size(),0,(struct sockaddr*)peer,len); // ssize_t nsendto(_sockfd,buffer,strlen(buffer),0,(struct sockaddr*)peer,len); if(n-1) { lg.LogMessage(Info,服务器回复消息失败,%d:%s,errno,strerror(errno)); } } } } void Usage(std::string proc) { std::coutUsage:\n\tproc local_Port\nstd::endl; } std::string onMessageDefault(std::string request) { return request[哈哈我收到了请求]; } //用popen来解析并处理命令消息 std::string ExcuteCommand(std::string command) { FILE* fppopen(command.c_str(),r); //打开fp文件失败 if(fpnullptr) { return excute错误; } std::string response; char buffer[1024]; while(1) { char* sfgets(buffer,sizeof(buffer),fp); if(snullptr) { break; } else { responsebuffer; } } fclose(fp); return response.empty()?success:response; } int main(int argc,char* argv[]) { if(argc!2) { Usage(argv[0]); return Usage_Err; } //记录输入的ip和port // std::string ipargv[1]; uint16_t portstd::stoi(argv[1]); //创建Udp_server对象 // std::unique_ptrUdp_server userstd::make_uniqueUdp_server(ip,port); // std::unique_ptrUdp_server userstd::unique_ptrUdp_server(new Udp_server(ip,port)); std::unique_ptrUdp_server userstd::unique_ptrUdp_server(new Udp_server(ExcuteCommand,port)); user-Init(); user-Start(); return 0; }udp_client.cc#includeiostream #includestring #includecerrno #includecstring #includeunistd.h #include sys/socket.h #include sys/types.h #include netinet/in.h #includearpa/inet.h #includeLog.hpp void Usage(const std::string process) { std::coutUsage:\n\tprocess server_ip server_portstd::endl; } int main(int argc,char* argv[]) { if(argc!3) { Usage(argv[0]); return 2; } //获取服务器的端口号和ip地址 std::string server_ipargv[1]; uint16_t server_portstd::stoi(argv[2]); //创建套接字 int socksocket(AF_INET,SOCK_DGRAM,0); if(sock0) { std::cerrsocket创建失败:strerror(errno)std::endl; return 1; } std::cout创建套接字成功sockstd::endl; //绑定套接字(客户端不用绑定因为同时可以有多个客户端发消息所以代码不能写死在sendto的时候自动就绑定了) //一旦绑定了这个app的客户端就占用了一个端口但是市面上有那么多的端口显然不能都满足于是让操作系统自动选择绑定的端口 //服务器的信息 struct sockaddr_in server; bzero(server,sizeof(server));//把local清空 server.sin_familyAF_INET; server.sin_porthtons(server_port);//htons是主机序列转网络序列 server.sin_addr.s_addrinet_addr(server_ip.c_str());//将char*类型转换成网络地址 socklen_t lensizeof(server); //客户端一直发送数据 while(1) { std::string inbuffer; std::cout请输入std::endl; getline(std::cin,inbuffer); ssize_t nsendto(sock,inbuffer.c_str(),inbuffer.size(),0,(struct sockaddr*)server,len); if(n0) { char buffer[1024]; struct sockaddr_in temp; socklen_t len2sizeof(temp); ssize_t mrecvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)temp,len2); if(m0) { buffer[m]0; std::cout服务器回复:bufferstd::endl; } else { break; } } else { break; } } close(sock); return 0; }

相关文章:

网络的历史及socket接口了解

一、网络发展历史 (这一部分只是了解一下即可) 在最开始,每一台计算机都是独立的计算机,如果我们两个人需要协同作业,都需要一个人先做一部分,然后拷贝下来,到另外一台主机上交由另外一…...

LTECleanerFOSS 项目推荐

LTECleanerFOSS 项目推荐 【免费下载链接】LTECleanerFOSS The last Android cleaner youll ever need! 项目地址: https://gitcode.com/gh_mirrors/lt/LTECleanerFOSS 项目基础介绍 LTECleanerFOSS 是一个开源项目,旨在清理和优化 LTE 网络相关的数据。该项…...

开源项目推荐:Polyfill Library

开源项目推荐:Polyfill Library 【免费下载链接】polyfill-library NodeJS module to create polyfill bundles tailored to individual user-agents. 项目地址: https://gitcode.com/gh_mirrors/pol/polyfill-library 1. 项目基础介绍 Polyfill Library 是…...

硬件加速视频转码工具:基于Android MediaCodec API的Transcoder项目推荐

硬件加速视频转码工具:基于Android MediaCodec API的Transcoder项目推荐 【免费下载链接】Transcoder 🎞 Hardware-accelerated video transcoding using Android MediaCodec APIs. Supports cropping, concatenation, clipping, audio processing, vide…...

10分钟上手!REST API自动化测试神器:从测试到文档一键搞定

10分钟上手!REST API自动化测试神器:从测试到文档一键搞定 【免费下载链接】rest-client A tool for automated testing REST API, generating exquisite testing report and REST API documentation. 项目地址: https://gitcode.com/gh_mirrors/rest/…...

Django-Dynamic-Scraper入门教程:从零开始构建你的第一个动态爬虫

Django-Dynamic-Scraper入门教程:从零开始构建你的第一个动态爬虫 【免费下载链接】django-dynamic-scraper Creating Scrapy scrapers via the Django admin interface 项目地址: https://gitcode.com/gh_mirrors/dj/django-dynamic-scraper Django-Dynamic…...

go-wkhtmltopdf在AWS Lambda中的应用:无服务器PDF生成方案

go-wkhtmltopdf在AWS Lambda中的应用:无服务器PDF生成方案 【免费下载链接】go-wkhtmltopdf Golang commandline wrapper for wkhtmltopdf 项目地址: https://gitcode.com/gh_mirrors/go/go-wkhtmltopdf go-wkhtmltopdf是一个Golang命令行包装器,…...

【亲测免费】 IBAN.js - 国际银行账号验证与格式化工具

IBAN.js - 国际银行账号验证与格式化工具 【免费下载链接】iban.js IBAN & BBAN validation, formatting and conversion in Javascript 项目地址: https://gitcode.com/gh_mirrors/ib/iban.js 1. 项目基础介绍与主要编程语言 IBAN.js 是一个开源的JavaScript库&am…...

ARM64架构手动编译libtorch,安装MKL/oneDNN加速模型推理,详细流程!

目录 前言: 一、依赖环境 二、下载pytorch源码 三、下载oneDNN源码 三、编译libtorch 四、整理libtorch 五、C调用libtorch 前言: libtorch官方并没有给出ARM64架构的安装文件,在ARM64环境下,libtorch需要手动编译。编译完成…...

简易CPU设计入门:内存读写(五)

专栏导航 上一篇:简易CPU设计入门:内存读写(四) 专栏目录 下一篇:无 项目代码下载 请大家首先准备好本项目所用的源代码。如果已经下载了,那就不用重复下载了。如果还没有下载,那么&#xf…...

JAVA软件开发岗位高频技术面筋(持续更新)

一.jdk8 特性 1.Lambda表达式 使用匿名内部类处理,减少内部类的编写,提高系统可读性。支持函数式编程。 2.Stream API 流操作数据时,外部变量声明为final,确保变量在Lambda表达式中不被修改。 支持并行流,实现原理多线…...

roop-unleashed 项目亮点解析

roop-unleashed 项目亮点解析 【免费下载链接】roop-unleashed Evolved Fork of roop with Web Server and lots of additions 项目地址: https://gitcode.com/gh_mirrors/ro/roop-unleashed 1. 项目的基础介绍 roop-unleashed 是一个开源项目,旨在提供一个…...

roop-unleashed 的项目扩展与二次开发

roop-unleashed 的项目扩展与二次开发 【免费下载链接】roop-unleashed Evolved Fork of roop with Web Server and lots of additions 项目地址: https://gitcode.com/gh_mirrors/ro/roop-unleashed 1、项目的基础介绍 roop-unleashed 是一个开源项目,旨在…...

开源项目 Adobe-GenP 亮点详解

开源项目 Adobe-GenP 亮点详解 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP 1. 项目的基础介绍 Adobe-GenP 是一个开源项目,旨在为用户提供一个高效的…...

开源项目 Adobe-GenP 的扩展与二次开发潜力

开源项目 Adobe-GenP 的扩展与二次开发潜力 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP 1. 项目的基础介绍 Adobe-GenP 是一个开源项目,旨在提供一种…...

【跟韩工学Ubuntu第2课】 第2章 磁盘、LVM、文件系统与扩容备份-001篇】

文章目录《Linux系统管理与服务配置》第2章 磁盘、LVM、文件系统与扩容备份2.1 磁盘基础:分区与分区表2.2 实战1:磁盘分区实操2.3 实战2:LVM逻辑卷管理2.4 实战3:文件系统管理2.5 实战4:磁盘扩容与数据备份2.6 课后习题…...

AI系列:AI时代必懂的基础概念扫盲

目录 第一篇章:核心概念三兄弟 1. 人工智能(AI):让机器模仿人的智能 2. 机器学习(ML):实现AI的一种方法 3. 深度学习(DL):机器学习中非常强大的一种技术 …...

linux系统 Ventoy 制作U启

比起君子讷于言而敏于行,我更喜欢君子善于言且敏于行。 目录 1. 下载 Ventoy 2. 解压压缩包 3. 插入U盘并确认设备名 4. 安装Ventoy到U盘(会格式化U盘) 5. 复制ISO文件 6. 使用启动盘 Ventoy的优点 1. 下载 Ventoy wget https://github.com/v…...

Webpack5 处理 CSS文件

1、背景Webpack 本身仅能处理Js文件,无法识别CSS文件及代码。因此需在webpack.config.js文件中进行单独处理。2、基础框架搭建1、搭建简单项目框架执行 npm install -y 指令,生成 package.json文件执行 npm install webpack webpack-cli html-webpack-pl…...

华为OD机试双机位C卷-最佳植树距离(C/C++/Py/Java/Js/Go)

最佳植树距离 华为OD机试真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解 华为OD上机考试2026双机位C卷 华为OD机试双机位C卷 200分题型 题目描述 按照环保公司要求,小明需要在沙化严重的地区进行植树防沙工作,初步目标是种植一条直线的树带…...

jqdatasdk与Python量化策略结合:构建你的第一个交易模型

jqdatasdk与Python量化策略结合:构建你的第一个交易模型 【免费下载链接】jqdatasdk 简单易用的量化金融数据包(easy utility for getting financial market data of China) 项目地址: https://gitcode.com/gh_mirrors/jq/jqdatasdk jqdatasdk是一款简单易用…...

Awesome Programming for Kids揭秘:从Scratch Jr.到Python Turtle的完美进阶路径

Awesome Programming for Kids揭秘:从Scratch Jr.到Python Turtle的完美进阶路径 【免费下载链接】awesome-programming-for-kids A curated list of resources for teaching kids programming. 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-programmin…...

Zygisk API完全指南:用NeoZygisk开发模块的5个关键步骤

Zygisk API完全指南:用NeoZygisk开发模块的5个关键步骤 【免费下载链接】NeoZygisk Zygote injection with ptrace 项目地址: https://gitcode.com/gh_mirrors/ne/NeoZygisk NeoZygisk是一个基于ptrace的Zygote注入框架,它允许开发者构建模块并在…...

Awesome Programming for Kids深度解析:从玩具机器人到代码世界的桥梁

Awesome Programming for Kids深度解析:从玩具机器人到代码世界的桥梁 【免费下载链接】awesome-programming-for-kids A curated list of resources for teaching kids programming. 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-programming-for-kids…...

multierr与标准库兼容性:errors.Is和errors.As完美结合

multierr与标准库兼容性:errors.Is和errors.As完美结合 【免费下载链接】multierr Combine one or more Go errors together 项目地址: https://gitcode.com/gh_mirrors/mu/multierr multierr是一个功能强大的Go错误处理库,允许开发者将一个或多个…...

汉字拼音转换神器pinyin:一站式解决注音、排序与检索难题

汉字拼音转换神器pinyin:一站式解决注音、排序与检索难题 【免费下载链接】pinyin :cn: 汉字拼音 ➜ hn z pīn yīn 项目地址: https://gitcode.com/gh_mirrors/pi/pinyin 在中文信息处理领域,准确高效的汉字拼音转换工具是不可或缺的基础组件。…...

避免90%状态错误:ADK-Python变量引用与上下文管理完全指南

避免90%状态错误:ADK-Python变量引用与上下文管理完全指南 【免费下载链接】adk-python 一款开源、代码优先的Python工具包,用于构建、评估和部署灵活可控的复杂 AI agents 项目地址: https://gitcode.com/GitHub_Trending/ad/adk-python ADK-Pyt…...

解决ActualBudget项目Docker启动失败:从环境配置到日志分析的全流程指南

解决ActualBudget项目Docker启动失败:从环境配置到日志分析的全流程指南 【免费下载链接】actual A local-first personal finance app 项目地址: https://gitcode.com/GitHub_Trending/ac/actual ActualBudget是一款本地优先的个人财务管理应用,…...

终极解决方案:ActualBudget在GrapheneOS移动端的JIT编译问题全攻略

终极解决方案:ActualBudget在GrapheneOS移动端的JIT编译问题全攻略 【免费下载链接】actual A local-first personal finance app 项目地址: https://gitcode.com/GitHub_Trending/ac/actual ActualBudget作为一款本地优先的个人财务管理应用,为用…...

告别快捷键冲突:AeroSpace与DBeaver完美兼容的终极解决方案

告别快捷键冲突:AeroSpace与DBeaver完美兼容的终极解决方案 【免费下载链接】AeroSpace AeroSpace is an i3-like tiling window manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ae/AeroSpace AeroSpace作为一款类i3的macOS窗口管理器&am…...