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

[C++ 网络协议] 套接字和地址族、数据序列

目录

1. 套接字

1.1 在Linux平台下构建套接字

1.1.1 用于接听的套接字(服务器端套接字)

1.1.2 用于发送请求的套接字(客户端套接字)

1.2 在Windows平台下构建套接字

1.2.1 Winsock的初始化

1.2.2 用于接听的套接字(服务器端套接字)

1.2.3 用于发送请求的套接字(客户端套接字)

1.3 Linux和Windows套接字的区别

1.4 套接字特性

1.4.1 socket函数

1.4.1.1 协议族信息(domain形参)

1.4.1.2  套接字类型(Type形参)

1.4.1.2.1 面向连接的套接字(SOCK_STREAM)

1.4.1.2.2 面向消息的套接字(SOCK_DGRAM)

1.4.1.3 协议的最终选择(protocol形参)

2. 地址族和数据序列

2.1 网络地址

2.1.1 IPv4(常用)

2.1.1.1 网络地址和主机地址

2.1.2 端口号

2.1.3 bind函数

2.1.3.1 sockaddr_in结构体

2.1.4 网络字节序

2.1.5 字节序转换

2.1.6 网络地址的初始化和分配

2.1.6.1 inet_addr函数

2.1.6.2 inet_aton函数(Windows不存在此函数)

2.1.6.3 inet_ntoa函数(和inet_aton函数相反)

2.1.6.4 INADDR_ANY常数

2.1.6.5 WSAStringToAddress函数(只有Windows平台有,不利于兼容性)

2.1.6.6 WSAAddressToString函数(只有Windows平台有,不利于兼容性)

2.1.6.7 服务器端初始化IP地址时非常明确,为什么还要进行IP的初始化呢?

3.其余流程函数

3.1 进入连接等待状态(listen函数)

3.2 受理客户端连接请求(accpet函数)

3.3 客户端请求连接(connect函数)

4. 基于TCP的服务器端/客户端函数调用关系


网络编程:编写程序使两台连网的计算机进行数据交换。

1. 套接字

操作系统提供名为套接字的部件,套接字是网络数据传输用的软件设备,它能够连接到因特网上,与远程计算机进行数据传输。

1.1 在Linux平台下构建套接字

对于Linux而言,socket操作与文件操作没有区别。如:close函数不仅可以关闭文件也可以关闭套接字。

1.1.1 用于接听的套接字(服务器端套接字)

第一步:调用socket函数创建套接字

#include<sts/socket.h>
int socket(int domain,int type,int protocol);
成功返回文件描述符,失败返回-1

第二步:调用bind函数分配IP地址和端口号

#include<sts/socket.h>
int bind(int sockfd,struct sockaddr* myaddr,socklen_t addrlen);
成功返回0,失败返回-1

第三步:调用listen函数转为可接收请求状态

#include<sts/socket.h>
int listen(int sockfd,int backlog);
成功返回0,失败返回-1

第四步:调用accept函数受理连接请求

#include<sts/socket.h>
int accept(int sockfd,struct sockaddr* addr,socklen_t* addrlen);
成功返回文件描述符,失败返回-1

accpet函数一直等待,直到有连接请求时,才会有返回值。

第五步:调用write函数发送数据

#include<unistd.h>ssize_t write(int fd,const void* buf,size_t nbytes);
成功则返回写入的字节数,失败返回-1

fd:文件描述符参数

buf:保存要传输数据的缓冲地址值

nbytes:要传输数据的字节数

第六步:关闭套接字

#include<unistd.h>int close(int fd);
成功返回0,失败返回-1

fd:文件描述符参数。 

close函数不仅可以关闭文件也可以关闭套接字。 客户端调用close会向服务端的客户端套接字文件描述符传递EOF。

1.1.2 用于发送请求的套接字(客户端套接字)

第一步:调用socket函数创建套接字

如上。

第二步:调用connect函数连接服务器端

#include<sts/socket.h>
int connect(int sockfd,struct sockaddr* serv_addr,socklen_t addrlen);
成功返回0,失败返回-1

第三步:调用read函数读取服务器传输的信息

#include<unistd.h>ssize_t read(int fd,void *buf,size_t nbytes);
成功则返回接收的字节数(但遇到文件结尾则返回0),失败返回-1

fd:数据接收对象的文件描述符参数

buf:保存接收数据的缓冲地址值

nbytes:要接收数据的字节数

第四步:关闭套接字

如上。

1.2 在Windows平台下构建套接字

在Windows平台下构建套接字要先进行Winsock的初始化。

1.2.1 Winsock的初始化

初始化版本库

#include<winsock2.h>int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
成功返回0,失败返回非0的错误代码值

wVersionRequested:WORD是通过typedef定义的unsigned short类型,这个参数是提供套接字版本信息。可借助MAKEWORD宏函数来构建版本信息,如:

MAKEWORD(1,2);       //主版本为1,副版本为2,返回0x0201
MAKEWORD(2,2);       //主版本为2,副版本为2,返回0x0202

lpWSAData:传入WSADATA型结构体变量地址(LPWSADATA是WSADATA的指针类型),调用完函数后会将相关参数,填充到这个参数里。

WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{......
}

注销版本库

#include<winsock2.h>int WSACleanup(void);
成功返回0,失败返回SOCKET_ERROR

销毁Winsock相关库,无法再调用Winsock相关函数。

1.2.2 用于接听的套接字(服务器端套接字)

 第一步:调用socket函数创建套接字

#include <winsock2.h>
SOCKET socket(int af,int type,int protocol);
成功返回套接字句柄,失败返回INVALID_SOCKET

第二步:调用bind函数分配IP地址和端口号

#include <winsock2.h>
int bind(SOCKET s,const struct sockaddr* name,int namelen);
成功返回0,失败返回SOCKET_ERROR

第三步:调用listen函数转为可接收请求状态

#include <winsock2.h>
int listen(SOCKET s,int backlog);
成功返回0,失败返回SOCKET_ERROR

第四步:调用accept函数受理连接请求

#include <winsock2.h>
SOCKET accept(SOCKET s,struct sockaddr* addr,int* addrlen);
成功返回文件描述符,失败返回INVALID_SOCKET

accpet函数一直等待,直到有连接请求时,才会有返回值。

第五步:调用send函数发送数据

#include<winsock2.h>
int send(SOCKET s,const char* buf,int len,int flags);
成功返回传输字节数,失败返回SOCKET_ERROR

 s:表示数据传输对象连接的套接字句柄值

buf: 保存待传输数据的缓冲地址值

len:要传输的字节数

flags:传输数据时用到的多种选项信息

第六步:关闭套接字

#include <winsock2.h>
int closeconnect(SOCKET s);
成功返回0,失败返回SOCKET_ERROR

1.2.3 用于发送请求的套接字(客户端套接字)

第一步:调用socket函数创建套接字

如上。

第二步:调用connect函数连接服务器端

#include <winsock2.h>
int connect(SOCKET s,const struct sockaddr* name,int namelen);
成功返回0,失败返回SOCKET_ERROR

第三步:调用recv函数,接收服务器端传来的数据

#include <winsock2.h>
int recv(SOCKET s,const char* buf,int len,int flags);
成功返回接收的字节数(收到EOF时为0),失败返回SOCKET_ERROR

 s:表示数据接收对象连接的套接字句柄值

buf: 保存接收数据的缓冲地址值

len:要接收的最大字节数

flags:接收数据时用到的多种选项信息

第四步:关闭套接字

如上。

1.3 Linux和Windows套接字的区别

  1. 文件描述符和句柄的区别:

    在Linux中,文件描述符是不区分文件和套接字的,即两个都是一样的

    在Windows中,句柄是区分文件和套接字的,并不完全一样。

    比较两个系统的socket、listen和accept函数,可以发现,其实Linux的int sockfd就对应于Windows的SOCKET s,即SOCKET这个类型,就存有套接字句柄整形值,也类似于一种编号。

  2. write和send的区别:

         在Linux中,有write也有send函数,来传输数据。

        在windows中,send函数只是比Linux中的write函数多了最后的flag参数。

1.4 套接字特性

1.4.1 socket函数

int socket(
int domain,    //套接字中使用的协议族(Protocol Family)信息
int type,      //套接字数据传输类型信息
int protocol   //计算机间通信中使用的协议信息
);
成功返回文件描述符,失败返回-1

 一个socket套接字=协议族+套接字类型+最终协议。

1.4.1.1 协议族信息(domain形参)

协议族:套接字通信中协议的分类。

名称协议族
PF_INET(常用)IPv4互联网协议族
PF_INET6IPv6互联网协议族
PF_LOCAL本地通信的UNIX协议族
PF_PACKET底层套接字的协议族
PF_IPXIPX Novell协议族

1.4.1.2  套接字类型(Type形参)

套接字类型:套接字的数据传输方式。

1.4.1.2.1 面向连接的套接字(SOCK_STREAM)

特点:

  1. 传输过程中数据不会丢失
  2. 按序传输数据
  3. 传输的数据不存在数据边界
  4. 套接字连接必须一一对应(一个客户端套接字对应服务器端的一个套接字,n个对应n个套接字)

总结:可靠的、按序传递的、基于字节的面向连接的数据传输方式的套接字注意接收和发送数据大小要相等。

特点:传输过程中数据不会丢失、传输的数据不存在数据边界,解释:

        在接收的套接字内部,有一个由字节数组组成的缓冲区,从传输端传过来的数据会先存储到这个缓冲区里,如果缓冲区满了,那么传输端就会停止传输,等待缓冲区中的数据被读取完,再继续传输。其中传输出错,也会进行重传服务,除特殊情况外,不会有数据丢失。

1.4.1.2.2 面向消息的套接字(SOCK_DGRAM)

特点:

  1. 快速传输
  2. 传输的数据可能丢失、损毁
  3. 传输的数据有数据边界
  4. 限制每次传输的大小

总结:不可靠的,不按序传递的、以数据的高速传输为目的的套接字,不存在连接的概念注意接收和发送数据次数要相等。

特点:传输的数据具有数据边界,解释:

        每次传输都有大小限制,如果超过了这个限制,那么就得分批发送,即意味着接收数据的次数应和传输次数相同。而面向连接的套接字,没有这个要求。

1.4.1.3 协议的最终选择(protocol形参)

第三个参数的意义:同一协议族中存在多个数据传输方式相同的协议

与套接字类型对应的:

  1. 面向连接的套接字:TCP套接字(IPPROTO_TCP),注意接收和发送数据大小要相等。
  2. 面向消息的套接字:UDP套接字(IPPROTO_UDP),注意接收和发送数据次数要相等。

2. 地址族和数据序列

IP(Internet Protocol网络协议):为收发网络数据而分配给计算机的值。

端口号:区分程序中创建的套接字而分配给套接字的序号。

2.1 网络地址

分为两类:IPv4(4字节地址族)、IPv6(16字节地址族)。

2.1.1 IPv4(常用)

IPv4标准的4字节IP地址,由网络地址主机地址组成。

2.1.1.1 网络地址和主机地址

IPv4分为如下A、B、C、D四种类型:

通过首字节可以判断其属于哪种类型:

首字节范围类型
0~127A
128~191B
192~223C

向对应IP地址主机传输数据,是先通过网络地址,查找到对应的路由器或交换机,再由路由器或交换机,根据主机ID将数据分发到主机上。如图:将数据发送到203.211.172.103上,会先找到网络地址为203.211.172的路由器,路由器再通过主机ID:103将数据传输给对应主机。

2.1.2 端口号

端口号由16位构成,可分配端口号范围为0~65535,但0~1023是知名端口号,会分配给特定应用程序,所以应当分配此范围之外的值。另外,虽然端口号不能重复,但TCP套接字和UDP套接字不会共用端口号,所以允许重复。例如:某TCP套接字用了9130端口,则其余TCP套接字不能使用此端口,但UDP套接字可以使用9130端口。

2.1.3 bind函数

#include<sts/socket.h>
int bind(int sockfd,struct sockaddr* myaddr,socklen_t addrlen);
成功返回0,失败返回-1

2.1.3.1 sockaddr_in结构体

sockaddr_in:保存IPv4地址信息的结构体

struct sockaddr_in
{sa_family_t    sin_family;    //地址族uint16_t       sin_port;      //16位TCP/UDP端口号struct in_addr sin_addr;      //32位IP地址char           sin_zero[8];   //不使用
}struct in_addr
{in_addr_t      s_addr;        //32位IPv4地址
}struct sockaddr
{sa_family_t    sin_family;        //地址族char           sa_data[14];       //地址信息
}

数据类型是POSIX(可移植操作系统接口),POSIX是为UNIX系列操作系统设立的标准。

1.sin_family成员

2.sin_port成员

保存16位端口号,是以网络字节序保存的。

3.sin_addr成员

保存32位IP地址信息,也是以网络字节序保存的。

4.sin_zero成员

无特殊含义。只是为了使结构体sockaddr_in和sockaddr结构体大小保持一致插入的成员。

为什么我们平常的使用,要先填充 sockaddr_in结构体,再转换为sockaddr结构体,而不直接填充sockaddr结构体呢?

答:因为sockaddr结构体中sa_data[14]数据的填充很麻烦,其中需包含IP地址和端口号,并且其余部分都要填充为0,才能使用。不如直接使用sockaddr_in结构体,再进行转换。填充复杂的原因是sockaddr结构体并不仅仅为IPv4而设计。

2.1.4 网络字节序

不同CPU中,向内存保存数据的方式有两种,一种是正序,直接保存,一种是倒序保存,这意味着,CPU解析数据的方式也分为两种:

  1. 大端序:高位字节存放到低位地址
  2. 小端序:高位字节存放到高位地址

所以,在数据传输时,必须统一方式,这种方式就称为网络字节序,即统一为大端序。即先把数据统一转化为大端序的格式,再进行网络传输,所以在填充sin_addr成员sin_port成员时需要以网络字节序保存。

2.1.5 字节序转换

主机字节序和网络字节序的相互转换,被称为字节序转换。有以下函数进行转换:

unsigned short htons(unsigned short);    //把short类型数据从主机字节序转换为网络字节序
unsigned short ntohs(unsigned short);    //把short类型数据从网络字节序转换为主机字节序
unsigned long htonl(unsigned long);      //把long类型数据从主机字节序转换为网络字节序
unsigned long ntohl(unsigned long);       //把long类型数据从网络字节序转换为主机字节序

htons中的h表示主机(host)字节序。

htons中的n表示网络(network)字节序。

htons中的s指的是short(short占2个字节,所以常用于端口号的转换)。

htonl中的l值得是long(Linux中long类型占4个字节,所以常用于IP地址的转换)。

2.1.6 网络地址的初始化和分配

2.1.6.1 inet_addr函数

#include <arpa/inet.h>
in_addr_t inet_addr(const char *string);
成功则返回32位大端序整数型值,失败则返回INADDR_NONE

这个函数帮助我们将字符串形式的IP地址转换为32位整数型数据,同时也会进行网络字节序转换。 同时它也会检测无效的IP地址

2.1.6.2 inet_aton函数(Windows不存在此函数)

inet_aton函数和inet_addr函数功能上相同。

#include <arpa/inet.h>
int inet_aton(const char *string,struct in_addr* addr);
成功则返回1,失败则返回0

string:含有需转换的IP地址信息的字符串地址值。

addr:将保存转换结果的in_addr结构体变量的地址值。

2.1.6.3 inet_ntoa函数(和inet_aton函数相反)

#include <arpa/inet.h>
char* inet_ntoa(struct in_addr* addr);
成功则返回转换的字符串地址值,失败则返回-1

将网络字节序32位整数型IP地址转换为字符串形式

注意:在使用此函数时,返回的结果是一个指针,指向字符串信息的地址,当第二次使用这个函数时,这个地址存有的字符串信息会被覆盖掉,所以在使用时,需要立即拷贝保存地址存有的字符串信息

2.1.6.4 INADDR_ANY常数

struct sockaddr_in addr;
memset(&addr,0,sizeof(addr));
...
addr.sin_addr.s_addr=htonl(INADDR_ANY);

INADDR_ANY常数:采用这种方式,会自动获取运行服务器端的计算机的IP地址,不必亲自输入,并且,若同一计算机中分配有多个IP地址(路由器这种),则只要端口号一致,就可以从不同IP地址里接收数据。所以服务器端优先考虑这种方式。

2.1.6.5 WSAStringToAddress函数(只有Windows平台有,不利于兼容性)

各种类型都是针对默认类型的typedef声明。

#include <winsock2.h>
INT WSAStringToAddress
(LPTSTR AddressString,INT AddressFamily,LPWSAPROTOCOL_INFO lpProtocolInfo,LPSOCKADDR lpAddress,LPINT lpAddressLength
);
成功返回0,失败返回SOCKET_ERROR

AddressString:含有IP地址和端口号的字符串地址值

AddressFamily:第一个参数中地址所属的地址族信息

lpProtocolInfo:设置协议提供者(Provider),默认为NULL
lpAddress:保存地址信息的结构体变量地址值

lpAddressLength:第四个参数中传递的结构体长度所在的变量地址值。

2.1.6.6 WSAAddressToString函数(只有Windows平台有,不利于兼容性)

各种类型都是针对默认类型的typedef声明。

#include <winsock2.h>
INT WSAAddressToString
(LPSOCKADDR lpsaAddress,DWORD dwAddressLength,LPWSAPROTOCOL_INFO lpProtocolInfo,LPTSTR lpszAddressString,LPDWORD lpdwAddressStringLength
);
成功返回0,失败返回SOCKET_ERROR

lpsaAddress:需要转换的地址信息结构体变量地址值

dwAddressLength:第一个参数中结构体的长度
lpProtocolInfo:设置协议提供者(Provider),默认为NULL

lpszAddressString:保存转换结果的字符串地址值
lpdwAddressStringLength:第四个参数中存有地址信息的字符串长度

2.1.6.7 服务器端初始化IP地址时非常明确,为什么还要进行IP的初始化呢?

因为:同一个计算机可能分配有多个IP地址,实际IP地址和计算机安装的NIC数量相等。所以服务器需要决定应接收哪个IP地址传来的数据,所以要服务器端要初始化IP地址。

3.其余流程函数

3.1 进入连接等待状态(listen函数)

当调用了listen函数,服务器端会阻塞,等待连接请求状态。意味着,只有在此之后客户端才能调用connect函数。

#include<sts/socket.h>
int listen(
int sockfd,            //希望进入等待连接请求状态的套接字文件描述符,传递的描述符套接字参数为服务器端套接字
int backlog            //连接请求等待队列的长度。
);
成功返回0,失败返回-1

如图:

        客户端连接请求本身也是从网络中接收到的一种数据,而接收数据就需要套接字,所以第一个参数服务器端套接字,就是充当门卫,可回复客户端请求,传输"请求已收到"的信号数据。第二个参数就是可以规定,连接请求等候的队列的大小,一般与服务器端特性有关,像频繁请求的web端则至少要15。

3.2 受理客户端连接请求(accpet函数)

#include<sys/socket.h>
int accpet(
int sock,                //服务器套接字的文件描述符
struct sockaddr* addr,   //保存发起连接请求的客户端地址信息的变量地址值
socklen_t* addrlen       //第二个参数的结构体长度。
);
成功则返回套接字文件描述符,失败则返回-1

accpet函数,受理连接请求等待队列中,待处理的客户端连接请求。函数调用成功,accept函数内部会产生用于数据I/O的套接字,并返回其文件描述符。这个套接字是自动创建的,并自动与发起连接请求的客户端建立连接。

3.3 客户端请求连接(connect函数)

#include<sys/socket.h>
int connect(
int sock,                    //客户端套接字文件描述符
struct sockaddr* servaddr,   //保存目标服务器端地址信息的变量地址值
socklen_t addrlen            //第二个参数的变量长度
);
成功返回0,失败返回-1

 connect函数只有以下情况之一才会返回:

  1. 服务器端接收连接请求,所谓的“连接请求”,并不意味着服务器端调用accpet函数,而是服务器端把连接请求信息记录到等待队列中。所以connect函数返回后并不立即进行数据交换
  2. 发生断网等异常情况而中断连接请求

4. 基于TCP的服务器端/客户端函数调用关系

        图中的总体流程整理如下:服务器端创建套接字后连续调用bind、listen函数进入等待状态,客户端通过调用connect函数发起连接请求。需要注意的是,客户端只能等到服务器端调用listen函数后才能调connect函数。同时要清楚,客户端调用connect函数前,服务器端有可能率先调用accept函数。当然,此时服务器端在调用accept函数时进入阻塞( blocking)状态,直到客户端调connect函数为止。

相关文章:

[C++ 网络协议] 套接字和地址族、数据序列

目录 1. 套接字 1.1 在Linux平台下构建套接字 1.1.1 用于接听的套接字(服务器端套接字) 1.1.2 用于发送请求的套接字(客户端套接字) 1.2 在Windows平台下构建套接字 1.2.1 Winsock的初始化 1.2.2 用于接听的套接字(服务器端套接字) 1.2.3 用于发送请求的套接字(客户端套…...

AI 绘画Stable Diffusion 研究(八)sd采样方法详解

大家好&#xff0c;我是风雨无阻。 本文适合人群&#xff1a; 希望了解stable Diffusion WebUI中提供的Sampler究竟有什么不同&#xff0c;想知道如何选用合适采样器以进一步提高出图质量的朋友。 想要进一步了解AI绘图基本原理的朋友。 对stable diffusion AI绘图感兴趣的朋…...

线程池满了如何处理

某天搬砖时遇到一个问题&#xff0c;我创建了一个线程池执行任务&#xff0c;刚开始的时候还是一切&#xff0c;结果第二天发现有些任务没有正常执行。一看日志才发现是高峰期时线程池给我占用慢了&#xff0c;任务被丢掉了。 ​ 举个例子&#xff0c;我创建了一个线程池&#…...

Java多线程编程中的线程间通信

Java多线程编程中的线程间通信 基本概念&#xff1a; ​ 线程间通信是多线程编程中的一个重要概念&#xff0c;指的是不同线程之间如何协调和交换信息&#xff0c;以达到共同完成任务的目的。 线程间通信的目的 ​ 是确保多个线程能够按照一定的顺序和规则进行协作&#xff…...

write javaBean error, fastjson version 1.2.76

fastjson JSON.toJSONString 报错&#xff1a; > [0] JavaBeanSerializer.java->541: com.alibaba.fastjson.serializer.JavaBeanSerializer->write()> [1] JavaBeanSerializer.java->154: com.alibaba.fastjson.serializer.JavaBeanSerializer->write()>…...

Tomcat的部署及优化(多实例和动静分离)

目录 绪论 1、tomact 1.1 核心组件 1.2 什么是 servlet 1.3 什么是 JSP? 1.4 Tomcat 功能组件结构 1.5 Tomcat 请求过程 2、Tomcat 服务部署 2.1 tomcat自身优化&#xff1a; 2.2 内核优化 2.3 jvm 2.3.1 jvm配置 2.3.2 Tomcat配置JVM参数 2.3.3 jvm优化 3、tom…...

品牌推广革新之道:海外网红与内容营销的融合

随着数字时代的来临&#xff0c;品牌推广的方式正在经历着革命性的变化。传统的广告手段逐渐失去了吸引力&#xff0c;而内容营销正成为品牌推广的新宠儿。尤其是海外网红的崛起&#xff0c;不仅改变了推广方式&#xff0c;更重新定义了品牌与消费者之间的互动关系。本文Nox聚星…...

【 BERTopic应用 02/3】 分析卡塔尔世界杯推特数据

摄影&#xff1a;Fauzan Saari on Unsplash 一、说明 这是我们对世界杯推特数据分析的第3部分&#xff0c;我们放弃了。我们将对我们的数据进行情绪分析&#xff0c;以了解人们对卡塔尔世界杯的感受。我将在这里介绍的一个功能强大的工具包是Hugging Face&#xff0c;您可以在…...

TypeScript教程(三)变量声明

一、变量声明 变量是一种使用方便的占位符&#xff0c;用于引用计算机内存地址&#xff0c;可以将变量看做存储数据的容器 命名规则&#xff1a; 1.变量名称可以包含数字和字母 2.除了下划线_和美元$符号外&#xff0c;不能包含其他特殊字符&#xff0c;包括空格 3.变量名…...

【数据结构】堆的实现,堆排序以及TOP-K问题

目录 1.堆的概念及结构 2.堆的实现 2.1初始化堆 2.2销毁堆 2.3取堆顶元素 2.4返回堆的大小 2.5判断是否为空 2.6打印堆 2.7插入元素 2.8堆的向上调整 2.9弹出元素 2.10堆的向下调整 3. 建堆时间复杂度 4. 堆的应用 4.1 堆排序 4.2 TOP-K问题 1.堆的概念及结构 …...

释放马氏距离的力量:用 Python 探索多元数据分析

一、说明 马哈拉诺比斯距离&#xff08;Mahalanobis Distance&#xff09;是一种测量两个概率分布之间距离的方法。它是基于样本协方差矩阵的函数&#xff0c;用于评估两个向量之间的相似程度。Mahalanobis Distance考虑了数据集中各个特征之间的协方差&#xff0c;因此比欧氏距…...

【不限于联想Y9000P电脑关盖再打开时黑屏的解决办法】

不限于联想Y9000P电脑关盖再打开时黑屏的解决办法 问题的前言问题的出现问题拟解决 问题的前言 事情发生在昨天&#xff0c;更新了Win11系统后&#xff1a; 最惹人注目的三处地方就是&#xff1a; 1.可以查看时间的秒数了&#xff1b; 2.右键展示的内容变窄了&#xff1b; 3.按…...

策略模式实战应用

场景 假设做了个卖课网站&#xff0c;会员等级分为月vip、年vip、终生vip&#xff0c;每个等级买课的优惠力度不一样&#xff0c;传统的写法肯定是一堆的 if-else&#xff0c;现在使用策略模式写出代码实现 代码实现 策略模式的核心思想就是对扩展开放&#xff0c;对修改关闭…...

JAVA集合-Map

// 【Map】:双列集合&#xff0c;键值对形式存储&#xff0c;映射关系(kay,value) // 实现&#xff1a;HashMap // 子接口&#xff1a;SortedMap Map的子接口 // 实现类&#xff1a;TreeMap // HashMap // 1。可以插入null // …...

利用Simulink Test进行模型单元测试 - 1

1.搭建用于测试的简单模型 随手搭建了一个demo模型MilTestModel&#xff0c;模型中不带参数 2.创建测试框架 1.模型空白处右击 测试框架 > 为‘MilTestModel’创建 菜单 2.在创建测试框架对话框中&#xff0c;点击OK&#xff0c;对应的测试框架MilTestMode_Harness1就自动…...

深入探讨代理技术:保障网络安全与高效爬虫

1. Socks5代理与IP代理的区别与应用 Socks5代理和IP代理是代理技术中的两个重要方面&#xff0c;它们有着不同的特点和应用场景。Socks5代理是一种协议&#xff0c;支持TCP和UDP流量传输&#xff0c;适用于需要实时数据传输的场景&#xff0c;例如在线游戏或实时通信应用。而I…...

HDMI接口的PCB布局布线要求

高清多媒体接口&#xff08;High Definition Multimedia Interface&#xff09;&#xff0c;简称&#xff1a;HDMI&#xff0c;是一种全数字化视频和声音发送接口&#xff0c;可以发送未压缩的音频及视频信号。随着技术的不断提升&#xff0c;HDMI的传输速率也不断的提升&#…...

Linux tar包安装 Prometheus 和 Grafana(知识点:systemd Unit/重定向)

0. 介绍 用tar包的方式安装 Prometheus 和 Grafana Prometheus:开源的监控方案Grafana:将Prometheus的数据可视化平台 Prometheus已经有了查询功能为什么还需要grafana呢?Prometheus基于promQL这一SQL方言,有一定门槛!Grafana基于浏览器的操作与可视化图表大大降低了理解难…...

【Vue框架】用户和请求

前言 在上一篇 【Vue框架】Vuex状态管理 针对Vuex状态管理以getters.js进行说明&#xff0c;没有对其中state引入的对象进行详细介绍&#xff0c;因为整体都比较简单&#xff0c;也就不对全部做详细介绍了&#xff1b;但其中的user.js涉及到获取用户的信息、前后端请求的token…...

NGINX组件(rewrite)

一、location匹配的规则和优先级&#xff08;*&#xff09; URI&#xff1a;统一资源标识符&#xff0c;是一种字符串标识&#xff0c;用于标识抽象的或者是物理资源&#xff1b;如&#xff1a;文件、图片、视频等 nginx中的URI匹配的是&#xff1a;网址”/“后的路径 如&…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)

Name&#xff1a;3ddown Serial&#xff1a;FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名&#xff1a;Axure 序列号&#xff1a;8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...