网络编程基础api

news2024/11/18 23:24:47

1. IP 协议

1.1 IP 分片

(1)IP 分片和重组主要依靠 IP 头部三个字段:数据报标识、标志和片偏移

以太网帧的 MTU 是 1500 字节;

一个每个分片都有自己的 IP 头部,它们都具有相同的标识值,有不同的片偏移(数据部分的长度必须是 8 的整数倍),除了最后一个分片外,其他分片都设置 MF 标志;
每个分片的总长度字段被设置为该分片的长度;

1.2 路由机制

执行 route 可以查看路由表
在这里插入图片描述
第一项的目标地址是 default,即默认路由项,包含一个“G”标志,说明路由下一跳目标是网关;

  1. 查找路由表中和数据报目标的 IP 地址完全匹配的 IP 地址;
  2. 查找路由表中和数据报目标的 IP 地址具有相同网络号的 IP 地址(网络号为 IP 地址&&子网掩码,匹配长度越长越优先);
  3. 选择默认路由项;

ICMP 重定向报文会改变路由表缓冲,生成更合理的路由方式;

2. TCP 协议

TCP 是一对一的,UDP 适合多播和广播;

UDP 中应用程序每次执行一个写操作,就会发送一个 UDP 数据报;接收方必须及时针对每一个 UDP 数据报执行读操作,否则会丢包,如果没有足够的应用程序缓冲区,UDP 数据可能被截断;

2.1 TCP 状态转移

(1)服务器通过 listen 系统调用进入 LISTEN 状态,监听到某个连接请求时(收到 SYN),将该连接放入内核等待队列,发送 SYN + ACK,收到 ACK 后,进入 ESTABLISHED 状态;

(2)客户端通过 connect 系统调用,该函数首先发送 SYN,使状态转移到 SYN_SENT 状态;

connect 调用失败的两个场景:(立即返回初始的 CLOSED 状态)

  1. 目标端口不存在,或其处于 TIME_WAIT 状态,服务器返回 RST 段
  2. 目标端口存在,但 connect 在超时时间内未收到服务器的确认报文段

connect 调用成功,转移至 ESTABLISHED 状态;

(3)客户端在 FIN_WAIT_2 状态时,未等服务器关闭连接强行退出;

此时客户端连接由内核接管,称为孤儿连接;tcp_max_orphanstcp_fin_timeout 定义了内核能接管的孤儿连接数目及其在内存中生成的时间;

(4)TIME_WAIT 状态存在的原因:

可靠的终止 TCP 连接
保证让迟来的 TCP 报文段被丢弃

(5)异常终止连接;

应用可以通过 socket 选项 SO_LINGER 来发送 RST 报文段;

2.2 TCP 数据流

(1)交互数据:仅包含很少字节,对实时性要求高,如 telnet,ssh 等;

客户端每个键入就会发送一个 TCP 数据报;客户端会立即确认,服务器可能使用延迟确认;

(2)成块数据:长度通常为最大数据长度,对传输效率要求高,如 ftp;

2.3 带外数据

紧急指针指向带外数据最后一个字节的下一个位置,因此仅能识别带外数据的最后一个字节;

2.4 拥塞控制

控制发送窗口(SWND),即发送端能连续发送的 TCP 报文段的数量

3. HTTP 协议

HTTP 请求中的头部字段可按任意顺序排序,目标主机名是必须包含的头部字段;

3.1 请求

(1)请求行;格式为:请求方法 ------ 目标资源 URL ------ 版本号(------ 代表空格或 \t(可能为多个));
(2)多个头部字段行;一个头部字段是一行,请求行和每个头部字段行必须以< CR >< LF >结尾(回车符及换行符)
(3)空行;所有头部字段之后,需要包含一个空行(回车符及换行符),标识头部字段的结束
(4)可选消息体;若消息体为空,头部字段必须包含该消息体长度的字段”Content-Length“

3.2 应答

(1)状态行;
(2)头部字段行;

HTTP 是一种无状态的协议,使用额外的手段来保持 HTTP 连接状态;
Cookie 是服务器发送给客户端的特殊信息,客户端每次向服务器发送请求时带上这个信息,就可以帮助服务器区分不同客户;

(3)空行;
(4)请求数据;

在这里插入图片描述

4. 整体流程

本地名称查询:/etc/hosts 存储了目标主机名及其对应 IP 地址

(1)如果在 /etc/hosts 未找到目标机器名对应的 IP 地址,会使用 DNS 服务;这个顺序可由 /etc/host.conf 配置

(2)DNS 服务:首先读取 /etc/resolv.conf,获取 DNS 服务器的 IP 地址,发送 UDP 报文段;

到达 IP 层时,会查询路由表,获得下一跳的 IP 地址,再调用网络驱动程序,根据这个地址获得其 MAC 地址(如果没有,会使用 ARP 协议)

5. socket

5.1 socket 地址族

5.1.1 字节序

(1)大端序:高位在内存低地址处(网络字节序,JAVA 虚拟机采用大端序)
------- 小端序:高位在内存高地址处(主机字节序)

(2)字节序的转换函数,long 函数通常转换 IP 地址,short 通常转换端口号;
在这里插入图片描述
转换函数源码:通过移位实现;

5.1.2 通用 socket 地址

(1)socket 结构体
在这里插入图片描述
sa_family 表示地址族类型;
sa_data 存放 socket 地址值,不同协议族有不同含义和长度,14 字节的 sa_data 无法完全容纳多数协议族的地址值;

协议族地址族描述地址含义及长度
PF_UNIXAF_UNIXUNIX 本地域协议族文件路径名,长度可达108字节
PF_INETAF_INETTCP/IPv4协议族16 位端口号和32位 P地址,共6字节
PF_INET6AF_INET6TCP/IPv6 协议族16 位端口号,32位流标识,128位IP地址,32位范围ID,共26字节

(2)Linux 定义了新的通用 socket 地址结构体
在这里插入图片描述
_ss_align 用于内存对齐作用;

5.1.3 专用 socket 地址

通用地址涉及位操作;

#include <sys/un.h>
struct sockaddr_un
{
	sa_family_t sin_family;  /*AF_UNIX*/
	char sun_path[108];		 /*文件路径名*/
};
----------------------------------------------------------------
struct sockaddr_in
{
	sa_family_t sin_family;  /*AF_INET*/
	u_int16_t sin_port		 /*端口号, 要用网络字节序表示*/
	struct in_addr sin_addr; /*IPv4 地址结构体*/
};
struct in_addr
{
	u_int32_t s_addr;		/*IPv4地址,要用网络字节序表示*/
};
----------------------------------------------------------------
struct sockaddr_in6
{
	sa_family_t sin6_family;  /*AF_INET6*/
	u_int16_t sin6_port;		 /*端口号,要用网络字节序表示*/
	u_int32_t sin6_flowinfo;	 /*流信息,应设置为 0*/
	struct in6_addr sin6_addr; /*IPv6 地址结构体*/
	u_int32_t sin6_scope_id;	/*暂未使用*/
};
struct in6_addr
{
	unsigned char sa_addr[16];		/*IPv6地址,要用网络字节序表示*/
};

所有专用 socket 地址(以及 sockaddr_storage)类型在实际使用时都需要转化为通用 socket 类型 sockaddr(强制转换即可)

如何进行的转换?

5.1.4 IP 地址转换

注意:点分十进制字符串是主机字节序,整数为网络序;

#include <arpa/inet.h>
/*
点分十进制转换为整数
失败返回 INADDR_NONE
*/
in_addr_t inet_addr( const char* strptr );  
/*
点分十进制转换为整数,将结果存储与 inp 指向结构中,
成功返回 1,失败返回 0
*/
int inet_aton( const char* cp, struct in_addr* inp );
/*整数转换为点分十进制*/
char* inet_ntoa( struct in_addr in );
----------------------------------------------------
/*
点分十进制字符串转换为整数
成功返回1
失败返回0,设置errno 
*/
int inet_pton( int af, const char* src. void* dst );
/*
整数转换为点分十进制字符串
成功返回目标存储单元地址
失败返回 NULL 并设置 errno
*/
const char* inet_ntop( int af, const void* src. char* dst, socklen_t cnt );

这里注意:inet_ntoa函数内部使用静态变量存储转换结果,函数返回值指向该静态内存,是不可重入的(会互相干扰)

转换结果存储在 dst 指向内存中;af 指定地址族,可以是 AF_INET 或 AF_INET6;参数 cnt 指定目标存储单元大小,取值参考下面;

#include <netinet/in.h>
#define INET_ADDRSTRLEN 16  	/*用于 IPv4 */
#define INET6_ADDRSTRLEN 46		/*用于 IPv6 */

5.2 操作 socket

5.2.1 创建

指定地址族;socket 是一个文件描述符;

#include <sys/types.h>
#include <sys/socket.h>
/*
成功返回 socket 文件描述符
失败返回 -1 并设置 errno
*/
int socket( int domain, int type, int protocol );

(1)domain 指明协议族,PF_**;
(2)type 指定服务类型,SOCK_STREAM(流服务)和 SOCK_UGRAM(数据报)对 TCP/IP 而言,前者表示使用 TCP,后者为 UDP;

服务类型可以和标志进行与运算:SOCK_NONBLOCK(新创建的 socket 设为非阻塞) 和 SOCK_CLOEXEC (fork 创建子进程时在子进程关闭该 socket);

(3)protocol;应该设置为 0;

5.2.2 命名

socket 命名:将一个 socket 与 socket 地址绑定;命名后客户端才知道如何连接它;客户端通常不需要命名 socket,采用匿名方式(操作系统自动分配);

#include <sys/types.h>
#include <sys/socket.h>
/*
成功返回 0
失败返回 -1 并设置 errno
EACCES 表示被绑定的地址是受包含的地址,仅超级用户能够访问,例如普通用户绑定知名端口
EADDRINUSE 被绑定的地址正在使用中,比如绑定到一个处于 TIME_WAIT 的 socket 地址
*/
int bind( int sockfd, const struct sockaddr* my_addr, socklen_t addrlen );

addrlen 指出 socket 地址的长度;

5.2.3 监听 socket

创建监听队列以存放待处理的客户连接;

#include <sys/socket.h>
/*
成功返回 0
失败返回 -1 并设置 errno
*/
int listen( int sockfd, int backlog );

backlog 参数提示内核监听队列的最大长度,表示处于完全连接状态(ESTABLISHED)的 socket 上限,典型值为 5;超过该值,服务器不再受理新的连接,客户端收到 ECONNREFUSED 错误;

处于半连接状态的 socket 上限由 /proc/sys/net/ipv4/tcp_max_syn_backlog 内核参数定义

5.2.4 接收连接

简单的从 listen 监听队列中接收一个连接,不关心连接处于哪种状态,例如建立连接后,断开客户端网络或直接退出客户端(处于 CLOSE_WAIT状态),都能调用成功;

#include <sys/types.h>
#include <sys/socket.h>
/*
成功返回一个新的连接 socket,唯一标识了被接收的连接
失败返回 -1 并设置 errno
*/
int accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen );

sockfd 是 listen 系统调用监听 socket;
addr 获取远端 socket 地址,该地址长度由 addrlen 指出;

accept调用成功返回的连接 socket 至少完成了三次握手的前两个;

5.2.5 发起连接
/*
成功返回 0
失败返回 -1 并设置 errno
*/
int connect( int sockfd, const struct sockaddr *serv_addr, socklen_t *addrlen );

serv_addr 为服务器监听,socket,addrlen 为这个地址长度;

常见 errno:
ECONNREFUSED,目标端口不存在,连接被拒绝
ETIMEDOUT,连接超时

connect成功返回后,TCP 三次握手已完成

5.2.6 关闭连接

关闭连接只是将其引用计数减1,等其为0时,才真正关闭;

#include <unistd.h>
int close( int fd );

立即终止连接(不是将引用计数减1)

#include <sys/socket.h>
/*
成功返回 0
失败返回 -1 并设置 errno
*/
int shutdown( int sockfd, int howto );

howto 取值为:

  1. SHUT_RD,关闭读,不能对其执行读操作,接收缓冲区的数据都被丢弃
  2. SHUT_WR,关闭写,之前发送缓冲区数据会在真正关闭前发送出去,处于半连接状态;
  3. SHUT_RDWR,都关闭

5.3 数据读写

对文件的读写操作 readwrite 可以使用,但有专门的系统调用,增加了对数据读写的控制;

5.3.1 TCP 数据读写
/*
失败返回 -1 并设置 errno
*/
ssize_t recv( int sockfd, void *buf, size_t len, int flags );
ssize_t send( int sockfd, const void *buf, size_t len, int flags );

buf 和 len 分别为缓冲区的位置和大小,recv 成功返回实际读到的数据,返回 0 意味对方关闭连接;
send 成功返回实际写入的数据的长度
在这里插入图片描述
flags 参数只对 sendrecv的当前调用生效,一般设为 0;

5.3.2 UDP 数据读写
/*
失败返回 -1 并设置 errno
*/
ssize_t recvfrom( int sockfd, void *buf, size_t len, int flags, 
				  struct sockaddr* src_addr, socklen_t* addrlen );
ssize_t sendto( int sockfd, const void *buf, size_t len, int flags 
				const struct sockaddr* dest_addr, socklen_t addrlen );

recvfromsendto 也可用于面向连接的 socket 数据读写,只需最后两个参数设为 NULL;

5.3.3 通用数据读写
#include <sys/socket.h>
ssize_t recvmsg( int sockfd, struct msghdr* msg, int flags );
ssize_t sendmsg( int sockfd, struct msghdr* msg, int flags );
struct msghdr
{
	void* msg_name;				/* socket地址 */
	socklen_t msg_namelen;		/* socket地址长度 */
	struct iovec* msg_iov;		/* 分散的内存块,数组首地址 */
	int msg_iovlen;				/* 分散的内存块数量 */
	void* msg_control;			/* 指向辅助数据的起始位置 */
	socklen_t msg_controllen;	/* 辅助数据的大小 */
	int msg_flags;			/* 复制函数中的 flags 参数,并在调用过程中更新 */
};
struct iovec
{
	void* iov_base;		/* 内存起始地址 */
	size_t iov_len;		/* 这块内存长度 */
};

(1)对 TCP 协议,msg_name 必须设为 NULL;
(2)iovec 封装了一块内存,msg_iovlen 指定了这样的对象有几个;

recvmsg 而言,数据被读取并存放在 msg_iovlen 块分散内存中,这些内存由 msg_iov 指向的数组指定,称为分散读;
sendmsg 而言,msg_iovlen 块分散内存中的数据将被一并发送,称为集中写;

(3)msg_flags 无需设定,会复制 recvmsg/sendmsg的 flags 参数;

5.4 带外标记

判断下一个被读取到的数据是否是带外数据,若是,返回 1 ,之后可以利用 MSG_OOB 标志的 recv 调用来接收,否则,返回 0;

#include <sys/socket.h>
int sockatmark( int sockfd );

5.5 地址信息函数

#include <sys/socket.h>
/* 
获取 sockfd 对应本端 socket 地址
成功返回 0
失败返回 -1 并设置 errno
*/
int getsockname( int sockfd, struct sockaddr* address, socklen_t* address_len );
/* 获取 sockfd 对应远端 socket 地址*/
int getpeername( int sockfd, struct sockaddr* address, socklen_t* address_len );

如果实际 socket 地址长度大于 address 指向内存,那么该 socket 地址会被截断;

5.6 socket 选项

#include <sys/socket.h>
/* 
成功返回 0
失败返回 -1 并设置 errno
*/
int getsockopt( int sockfd, int level, int option_name, void* option_value, 
				socklen_t* restrict option_len );
/* 获取 sockfd 对应远端 socket 地址*/
int setsockopt( int sockfd, int level, int option_name, const void* option_value, 
				socklen_t* restrict option_len );
leveloption name数据类型是否需要特定的设定时机说明
SOL_SOCKET(通用选项)SO_REUSEADDRint重用本地地址
SOL_SOCKETSO_RCVBUFintTCP 接收缓冲区大小
SOL_SOCKETSO_SNDBUFintTCP 发送缓冲区大小
SOL_SOCKETSO_RCVLOWATintTCP 接收缓冲区低水位标记
SOL_SOCKETSO_SNDLOWATintTCP 发送缓冲区低水位标记
SOL_SOCKETSO_LINGERlinger若有数据待发送,则延迟关闭

对服务器而言,有些 socket 选项只能在 listen 之前设定,对监听 socket 设定的选项,对返回的连接 socket 将自动继承这些选项;
对客户端而言,这些选项应该在调用 connect 之前设定

(1)设置 TCP 接收/发送缓冲区大小时,系统会将其值加倍,并不得小于某个最小值;

TCP 接收缓冲区的最小值为 256 字节,发送缓冲区的最小值为 2048 字节

(2)SO_RCVLOWAT 和 SO_SNDLOWAT 一般被 IO 复用调用用来判断 socket 是否可读或可写;

(3)SO_LINGER 控制 close 关闭 TCP 的行为;

默认调用 close 会立即返回,TCP 模块负责把该 socket 对应 TCP 发送缓冲区中残留的数据发送给对方;

struct linger
{
	int l_onoff;	/* 开启(非0)还是关闭(0) */
	int l_linger;	/* 滞留时间 */		
};

l_onoff 为 0;该选项无效,close 采用默认行为;
l_onoff 不为 0,l_linger 为 0;close 立即返回,丢弃发送缓冲区数据,同时给对方发送一个 RST 报文段(异常终止一个连接);
l_onoff 不为 0,l_linger 大于 0;对于阻塞的 socket,close 等待 l_linger 时间,知道发送完所有残留数据并得到对方确认,否则,将返回 -1 并设置 errno 为 EWOULDBLOCK;如果 socket 是非阻塞的,close立即返回,此时需要根据其返回值和 errno 来判断残留数据是否发送完毕;

5.7 网络信息

网络信息 API 作用:实现主机名代替 IP,服务名代替端口号

5.7.1 根据主机名/IP 获取主机完整信息

如果在 /etc/hosts 未找到目标机器名对应的 IP 地址,会使用 DNS 服务;

#include <netdb.h>
struct hostent* gethostbyname( const char* name );
struct hostent* gethostbyaddr( const void* addr, size_t len, int type );
struct hostent
{
	char* h_name;			/*主机名*/
	char** h_aliases;		/*主机别名列表*/
	int h_addrtype;			/*地址族*/
	int h_length;			/*地址长度*/
	char** h_addr_list;		/*主机 IP 地址列表(网络字节序给出)*/
};

addr 是目标主机的 IP 地址,len 是 addr 所指 IP 地址长度;
type 是 addr 所指 IP 地址类型,取值为 AF_INFT / AF_INFT6;

5.7.2 根据名称/端口号获取服务的完整信息

实际上读取 /etc/services 文件获取服务信息;

#include <netdb.h>
struct servent* getservbyname( const char* name, const char* proto );
struct servent* getservbyport( int port, const char* proto );
struct servent
{
	char* s_name;			/*服务名*/
	char** s_aliases;		/*服务别名列表*/
	int s_port;				/*端口号族*/
	char* s_proto;			/*服务类型,见下*/
};

proto 指定服务类型,取值为 ”tcp“、 ”udp“、NULL(所有类型的服务)

注意:上述四个函数是不可重入的(线程不安全),可重入版本函数名结尾加 _r

5.7.3 getaddrinfo

通过主机名/服务名获得 IP/端口号,内部调用 gethostbynamegetservbyname

#include <netdb.h>
int getaddrinfo( const char* hostname, const char* service, const struct addrinfo* hints,
				 struct addrinfo** result );
struct addrinfo
{
	int ai_flags;				/*见下*/
	int ai_family;				/*地址族*/
	int ai_socktype;			/*服务类型,SOCK_STREAM 或 SOCK_DGRAM */
	int ai_protocol;			/*具体网络协议,通常设置为 0 */	
	socklen_t ai_addrlen;		/*socket 地址 ai_addr 的长度*/
	char* ai_canonname;			/*主机的别名*/
	struct sockaddr* ai_addr;	/*指向 socket 地址*/
	struct addrinfo* ai_next;	/*指向下一个addrinfo对象*/
};

result 指向一个链表,存储 getaddrinfo返回结果
在这里插入图片描述
hints 具有提示作用,当使用时,设置其前四个字段,其余必须被设置为 NULL;

getaddrinfo将给 result 隐式分配堆内存,必须通过下述函数进行释放

void freeaddrinfo( struct addrinfo* res );
5.7.4 getnameinfo

通过socket 地址同时获得 主机名和服务名,内部调用 gethostbyaddrgetservbyport

/*
成功返回 0
失败返回错误码
*/
void getnameinfo( const struct sockaddr* sockaddr, socklen_t addrlen, char* host
				  socklen_t hostlen, char* serv, socklen_t servlen, int flags );

在这里插入图片描述
在这里插入图片描述
将错误码转化为字符串形式;

const char* gai_strerror( int error );

6. 参考

《Linux高性能服务器》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1294759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能优化算法应用:基于孔雀算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于孔雀算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于孔雀算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.孔雀算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

十二要素超声波气象站-气象站科普百科

随着科技的发展&#xff0c;人们对气象信息的关注度越来越高。 一、十二要素超声波气象站实时监测 WX-CSQX12 十二要素超声波气象站通过超声波测量技术&#xff0c;对温度、湿度、风速、风向、气压、雨量、蒸发量等十二个气象要素进行实时监测。 二、智能分析 十二要素超声…

家电制造数字孪生5G智能工厂可视化系统,加速家电制造产业数字化转型

5G数字孪生、三维可视化与工业互联网的融合加速中国新型工业化进程&#xff0c;助推我国从制造大国迈进制造强国。家电行业是中国最具国际竞争力的产业之一&#xff0c;在企业数字化转型中&#xff0c;要求企业从生产设备到数字化系统&#xff0c;一系列的数字化、智能化改革已…

爱智EdgerOS之深入解析安全可靠的开放协议SDDC

一、协议简介 在 EdgerOS 的智慧生态场景中&#xff0c;许多智能设备或传感器的生命周期都与 SDDC 协议息息相关&#xff0c;这些设备可能是使用 libsddc 智能配网技术开发的&#xff0c;也有可能是因为主要功能上是使用其他技术如 MQTT、LoRa 等但是设备的上下线依然是使用上…

测试文档---智力冲刺

文章目录 项目背景测试计划UI测试接口测试手工测试 测试总结 项目背景 项目描述&#xff1a;“智力冲刺”是一款网页小游戏&#xff0c;就像我们平时看到的网页游戏一样&#xff0c;前端页面负责展示游戏效果&#xff0c;后端服务器来实现游戏的逻辑。在我们的“智力冲刺”游戏…

如何解压没有密码的7-zip文件?

7z压缩包设置了密码&#xff0c;解压的时候就需要输入正确对密码才能顺利解压出文件&#xff0c;正常当我们解压文件或者删除密码的时候&#xff0c;虽然方法多&#xff0c;但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么&#xff0c;忘记了7z压缩包的密码…

C //习题10.8 将第7题结果仍存入原有的“stu_sort“文件而不另建立新文件。

C程序设计 &#xff08;第四版&#xff09; 谭浩强 习题10.8 习题10.8 将第7题结果仍存入原有的"stu_sort"文件而不另建立新文件。 IDE工具&#xff1a;VS2010 Note: 使用不同的IDE工具可能有部分差异。 说明&#xff1a;此题同习题10.7的代码&#xff0c;唯一的区…

LangChain 23 Agents中的Tools用于增强和扩展智能代理agent的功能

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

KST指标底背离选股公式,通过变动率ROC合成动量震荡指标

KST指标&#xff08;KnowSureThing&#xff09;是由马丁普林斯&#xff08;Martin Pring&#xff09;于1992年发明的技术分析指标&#xff0c;目的在于及时识别价格趋势的变化和转折点&#xff0c;同时避免短期震荡指标不稳定的缺点。KST指标结合了四个周期的ROC&#xff08;变…

学习记录---kubernetes中备份和恢复etcd

一、简介 ETCD是kubernetes的重要组成部分&#xff0c;它主要用于存储kubernetes的所有元数据&#xff0c;我们在kubernetes中的所有资源(node、pod、deployment、service等)&#xff0c;如果该组件出现问题&#xff0c;则可能会导致kubernetes无法使用、资源丢失等情况。因此…

HarmonyOS学习 第2节 DevEco Studio工程介绍

工程配置页 界面布局介绍 代码编辑区、通知栏、工程目录区、预览区 工程目录区 便于理解&#xff0c;可以切换为 Ohos AppScope主要用于存放整个应用公共的信息与资源 entry默认的初始模块ets文件用于存放编写的代码文件configuration存放相应模块的配置文件resources对应模块…

上证指数近十年走势图

上证指数是中国股市的晴雨表&#xff0c;其近十年的走势图展现了中国经济波动、政策变化、国际形势等多重因素对股市的影响。让我们一起通过这张图&#xff0c;深入探讨上证指数的波动&#xff0c;了解其中的因果关系和背后的故事。 2013-2015&#xff1a;震荡上行 回顾近十年…

【FPGA】Verilog:BCD 加法器的实现

0x00 XOR 运算在 2 的补码加减法中的应用 2 的补码加减法的特点是&#xff0c;当从某个数中减去负数时&#xff0c;将其转换为正数的加法来计算&#xff0c;并将减去正数的情况转换为负数的加法来计算&#xff0c;从而将所有减法运算转换为加法运算。在这种情况下&#xff0c;…

windows系统nodeJs报错node-sass npm ERR! command failed

报错信息 npm WARN deprecated request2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated tar2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asa…

DDD架构思想专栏一《初识领域驱动设计DDD落地》

引言 最近准备给自己之前写的项目做重构&#xff0c;这是一个单体架构的小项目&#xff0c;后端采用的是最常见的三层架构。因为项目比较简单&#xff0c;其实采用三层架构就完全够了。但是呢&#xff0c;小编最近在做DDD架构的项目&#xff0c;于是就先拿之前写的一个老项目试…

解决Eslint和Prettier关于三元运算符的冲突问题

三元运算符Prettier的格式化 三元运算符Eslint的格式要求 解决办法 // eslint加入配置&#xff0c;屏蔽标红报错indent: [error, 2, { ignoredNodes: [ConditionalExpression] }]效果

HCIP —— BGP 基础 (上)

BGP --- 边界网关协议 &#xff08;路径矢量协议&#xff09; IGP --- 内部网关协议 --- OSPF RIP ISIS EGP --- 外部网关协议 --- EGP BGP AS --- 自治系统 由单一的组织或者机构独立维护的网络设备以及网络资源的集合。 因 网络范围太大 需 自治 。 为区分不同的AS&#…

智能优化算法应用:基于浣熊算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于浣熊算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于浣熊算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.浣熊算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

1 接口测试介绍

在软件测试工作中&#xff0c;接口测试是必不可少的。接口测试一般是发生在单元测试之后&#xff0c;系统测试之前。当开发人员输出API文档后&#xff0c;测试人员就可以开始编写接口测试用例了。接口测试可以让测试人员更早的介入&#xff0c;不需要等待前后端联调完成才开始测…

信息化,数字化,智能化三者是同一概念么?

引言 在当今科技和商业领域&#xff0c;信息化、数字化和智能化是三个极为关键的概念。信息化强调信息的获取、传递和应用&#xff0c;数字化则是将物理实体转化为数字形式&#xff0c;而智能化则赋予系统更高级的智能和自主性。这些概念的交汇与融合塑造着我们的现实&#xf…