[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函数为止。

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

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

相关文章

pytest框架快速进阶篇-pytest前置和pytest后置,skipif跳过用例

一、Pytest的前置和后置方法 1.Pytest可以集成unittest实现前置和后置 importunittestimportpytestclassTestCase(unittest.TestCase):defsetUp(self)->None:print(unittest每个用例前置)deftearDown(self)->None:print(unittest每个用例后置)classmethoddefsetUpClass…

jmeter中用户参数和用户定义的变量的区别

如果使用jmeter做过参数化的人都知道&#xff0c;参数化的方式有多种&#xff0c;其中一种就是使用用户定义的变量&#xff0c;还有一种是使用用户参数。那么&#xff0c;这两个有什么异同呢&#xff1f; 一、先说相同的点&#xff1a; 1、都可以参数化&#xff0c;以供sample…

allure测试报告

使用pytest结合Allure进行测试报告生成的简单教程 allure测试报告 Allure基于Java开发&#xff0c;因此我们需要提前安装Java 8或以上版本的环境。 ◆安装allure-pytest插件在DOS窗口输入命令“pip3 install allure-pytest”&#xff0c;然后按“Enter”键。 下载安装Allure…

使用 Docker 部署 canal 服务实现MySQL和ES实时同步

文章目录 0. 环境介绍0. 前置步骤1. 安装Kibana和Elasticsearch2. 安装Canal和Canal Adapter2.1 修改数据库配置2.1.1 修改配置2.1.2 验证mysql binlog配置2.1.3 查看日志文件2.1.4 用JDBC代码插入数据库 2.2 安装Canal Server2.3 安装Canal Adapter修改两处配置文件配置文件取…

初识mysql数据库之引入mysql客户端库

目录 一、下载第三方库 1. 准备工作 1. 使用mysql官网提供的库 2. yum源安装 二、测试第三方库是否可用 三、mysql常用接口介绍 1. 查看官方文档 2. 初始化 3. 关闭mysql 4. 连接mysql 5. 下达sql指令 四、一个简单的C客户端库连接mysql程序 1. 头文件 2. 初始化…

Could not resolve host: mirrorlist.centos.org; Unknown error解决方法

今天服务器安装完CentOS系统后&#xff0c;安装网络的时候&#xff0c;出现无法联网yum yum -y install net-tools 以上代码无法运行并报错&#xff0c;这里我要提醒大家&#xff0c;如果在初始安装的时候选中安装网络工具模块就不用在安装net-tools了&#xff0c;因为我选中…

vite跨域配置踩坑,postman链接后端接口正常,但是前端就是不能正常访问

问题一&#xff1a;怎么都链接不了后端地址 根据以下配置&#xff0c;发现怎么都链接不了后端地址&#xff0c;proxy对了呀。 仔细看&#xff0c;才发现host有问题 // 本地运行配置&#xff0c;及反向代理配置server: {host: 0,0,0,0,port: 80,// cors: true, // 默认启用并允…

爆肝整理,性能测试方法与关键指标以及瓶颈定位思路,一篇贯通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试方法 1、…

抓包工具Fiddler下载与安装

一、Fiddler介绍 1.Fiddler简介 Fiddler 是一款免费、灵活、操作简单、功能强大的 HTTP 代理工具&#xff0c;是目前最常用的 HTTP 抓包工具之一。可以抓取所有的 HTTP/HTTPS 包、过滤会话、分析请求详细内容、伪造客户端请求、篡改服务器响应、重定向、网络限速、断点调试等…

数据结构刷题训练:队列实现栈

目录 前言 1. 题目&#xff1a;使用队列实现栈 2. 思路 3. 分析 3.1 创建栈 3.2入栈 3.3 出栈 3.4 栈顶数据 3.5 判空和 “ 栈 ” 的销毁 4. 题解 总结 前言 我们已经学习了栈和队列&#xff0c;也都实现了它们各自的底层接口&#xff0c;那么接下我们就要开始栈和队列的专项刷…

go内存管理机制

golang内存管理基本是参考tcmalloc来进行的。go内存管理本质上是一个内存池&#xff0c;只不过内部做了很多优化&#xff1a;自动伸缩内存池大小&#xff0c;合理切割内存块。 基本概念&#xff1a; Page&#xff1a;页&#xff0c;一块 8 K大小的内存空间。Go向操作系统申请和…

2.Model、ModelMap和ModelAndView的使用详解

1.前言 最近SSM框架开发web项目&#xff0c;用得比较火热。spring-MVC肯定用过&#xff0c;在请求处理方法可出现和返回的参数类型中&#xff0c;最重要就是Model和ModelAndView了&#xff0c;对于MVC框架&#xff0c;控制器Controller执行业务逻辑&#xff0c;用于产生模型数据…

Spring Cloud构建微服务断路器介绍

什么是断路器 断路器模式源于Martin Fowler的Circuit Breaker一文。“断路器”本身是一种开关装置&#xff0c;用于在电路上保护线路过载&#xff0c;当线路中有电器发生短路时&#xff0c;“断路器”能够及时的切断故障电路&#xff0c;防止发生过载、发热、甚至起火等严重后果…

【Redis】使用Docker镜像配置集群时的Operation timed out问题

不知道有没有小伙伴跟我一样是使用的Docker镜像进行Redis集群案例模拟的&#xff08;三台虚拟机确实带不动 &#xff09;&#xff0c;然后我遇到了一个问题&#xff1a;Could not connect to Redis at 172.17.0.2:6379: Operation timed out 172.17.0.2是我其中一个Redis实例的…

如何测试Linux磁盘的读写速度

在Linux系统中也有很多命令可以测试硬盘的读写速度指标。以下是几个常用命令&#xff08;注意&#xff1a;在执行测试命令之前&#xff0c;请务必备份数据以避免数据丢失&#xff01; 1、dd 命令 首先挂载磁盘 mount /dev/sdb /testdd 命令可用于进行硬盘读写速度测试。 例…

android 开发中常用命令

1.反编译 命令&#xff1a;apktool d <test.apk> -o <folderdir> 其中&#xff1a;test.apk是待反编译文件的路径&#xff0c;folderdir是反编译后的文件的存储位置。 apktool d -f <test.apk> -o <folderdir> 注意&#xff1a;如果dir已经存在&am…

【Sklearn】基于决策树算法的数据分类预测(Excel可直接替换数据)

【Sklearn】基于决策树算法的数据分类预测&#xff08;Excel可直接替换数据&#xff09; 1.模型原理1.1 模型原理1.2 数学模型 2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果 1.模型原理 决策树是一种基于树状结构的分类和回归模型&#xff0c;它通过一系列…

MySql(干货)

写这篇博客的目的不是为了将介绍原理&#xff0c;而是为了Sql中的代码操作属实太多了&#xff0c;在这里进行一个汇总&#xff0c;方便查阅&#xff01;&#xff01;&#xff01; Sql分类 分类全称说明 DDL Data Definintion Language数据定义语言&#xff0c;用来定义数据库对…

微信小程序(由浅到深)

文章目录 一. 项目基本配置1. 项目组成2. 常见的配置文件解析3. app.json全局的五大配置4.单个页面中的page配置5. App函数6.tabBar配置 二. 基本语法&#xff0c;事件&#xff0c;单位1. 语法2. 事件3. 单位 三. 数据响应式修改四 . 内置组件1. button2. image3. input4. 组件…

k8s常用资源管理 控制

目录 Pod&#xff08;容器组&#xff09;&#xff1a;Pod是Kubernetes中最小的部署单元&#xff0c;可以包含一个或多个容器。Pod提供了一种逻辑上的封装&#xff0c;使得容器可以一起共享网络和存储资源 1、创建一个pod 2、pod管理 pod操作 目录 创建Pod会很慢 Pod&…