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

Linux 网络编程(二)——套接字编程简介

文章目录

2 Socket 套接字

2.1 什么是 Socket

2.2 Socket编程的基本操作

2.3 地址信息的表示

2.4 网络字节序和主机字节序的转换

2.4.1 字节序转换

2.4.2 网络地址初始化与分配

2.5 INADDR_ANY

2.6 Socket 编程相关函数

2.7 C标准中的 main 函数声明

2.8 套接字应用示例


2 Socket 套接字

2.1 什么是 Socket

套接字(Socket)是计算机网络数据通信的基本概念和编程接口,允许不同主机上的进程通过网络进行数据交换。一个套接字主要由以下三个部分组成

  • 网络地址:通常是 IP 地址,用于标识网络上的设备

  • 端口号:端口号在同一操作系统内区分不同套接字而设计的,用于标识设备上的特定应用或进程,端口号是一个16位数字,范围是0到65565

  • 协议:定义数据传输的规则和格式,如TCP和UDP

2.2 Socket编程的基本操作

  • 创建Socket:通过 socket() 系统调用创建一个 Socket,该调用返回 int 类型的文件描述符。
  • 绑定地址:对于服务器端,需要使用 bind() 系统调用将 Socket 绑定到一个特定的 IP 地址和端口号上,以便客户端能够连接。(客户端可绑可不绑)
  • 监听连接请求(仅适用于TCP):对于TCP服务器,需要使用 listen() 系统调用开始监听客户端的连接请求。
  • 接受连接(仅适用于TCP):使用 accept() 系统调用接受客户端的连接请求,返回一个新的 Socket 描述符,通过新的 Socket 描述符与客户端进行通信。
  • 发起连接(仅适用于TCP客户端):对于TCP客户端,使用 connect() 系统调用向服务器端发起连接请求。
  • 发送和接收数据:通过 send()recv() 系统调用(对于UDP, 使用sendto() recvfrom() 系统调用)发送和接收数据。
  • 关闭连接:通信结束后,使用 close() 系统调用关闭 Socket 连接。

2.3 地址信息的表示

在 Socket 编程中,应用程序使用的 IP 地址和端口号以结构体的形式进行了定义。Socket 编程的核心任务之一就是要正确填写主机地址和目标地址,因此,理解这些结构体的定义和使用方法至关重要。

struct sockaddr {sa_family_t		sin_family;		//地址族,IPV4:AF_INET IPv6:AF_INET6char            sa_data[14];    //地址信息
}
-----------------------------------------------------------------------
struct sockaddr_in {sa_family_t		sin_family;		//地址族,IPV4:AF_INET IPv6:AF_INET6uint16_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地址
}

分割线上的 sockaddr 结构体是 Socket 官方文档中函数的参数,但它仅包含一个地址族字段和一个字符数组用于存储地址数据,无法直接表示 IP 地址和端口号。因此,在实际开发中,我们通常会使用 sockaddr_in 来表示地址字段,然后通过强制类型转换将其转换为 sockaddr 类型。此外,在 sockaddr_in 中,还 “套娃” 了一个 in_addr 结构体,用于存放 IP 地址。(代码块中的数据类型可以参考 POSIX 文档)

2.4 网络字节序和主机字节序的转换

CPU 向内存保存数据的方式有两种,不同的 CPU 保存数据的方式可能也会有所不同

  • 大端字节序(大端存储):高位字节存放低地址部分
  • 小端字节序(小端存储):高位字节存放高地址部分

网络字节序是一种标准的字节存储顺序,用于在网络上传输数据。网络字节序是大端字节序,也就是说,当数据在网络上传输时,无论发送方和接收方的主机字节序是什么保存格式,都必须将数据转换为大端字节序进行传输。

2.4.1 字节序转换

// 将 32 位整数 从主机字节序转换为网络字节序        "Host to Network Long int"  
uint32_t htonl(uint32_t hostlong);// 将 32 位整数 从网络字节序转换为主机字节序        "Network to Host Long int"  
uint32_t ntohl(uint32_t netlong);// 将 16 位整数 从主机字节序转换为网络字节序         "Host to Network Short int" 
uint16_t htons(uint16_t hostshort);// 将 16 位整数 从网络字节序转换为主机字节序。       "Network to Host Short int" 
uint16_t ntohs(uint16_t netshort);

以下是字节序转换的测试例程

int main(int argc, char const *argv[])
{//主机端口(小端)unsigned short host_port = 0x1234;//网络端口(大端)unsigned short net_port;unsigned long host_addr = 0x12345678;unsigned long net_addr;net_port = htons(host_port);net_addr = htonl(host_addr);printf("host_port:%x\n",host_port);printf("net_port:%x\n",net_port);printf("host_addr:%lx\n",host_addr);    //%lx 长整形16进制printf("net_addr:%lx\n",net_addr);return 0;
}

2.4.2 网络地址初始化与分配

对于 IP 地址的表示,我们通常很少使用整数型数据来表示地址和端口,而是更倾向于使用点分十进制来表示 IP 地址。接下来介绍的函数都是针对点分十进制表示法的 IP 地址进行操作的,其中一些函数(如 inet_aton 和 inet_pton)还会帮助我们将转换后的地址直接存储在 struct in_addr 结构体中。

int inet_aton(const char *cp, struct in_addr *inp);
// 把IPv4点分十进制表示法的iP主机地址cp转换为二进制形式,
// 并将其存储在struct in_addr 结构体中(一步到位),成功返回1,失败返回0,只适用ip协议// 等价于inet_aton函数  唯一不同是inet_pton可以使用任意协议
int inet_pton(int af, const char *src, void *dst); 
/*
* af:AF_INET(ipv4)或AF_INET6(ipv6)
* src:包含ip地址字符串的字符数组
* dst:指向一个足够大的缓冲区,用于存储转换后的二进制ip地址
* return:成功返回0,失败返回-1,同时设置errno
*/char *inet_ntoa(struct in_addr in);
/*
* 返回一个以网络字节序表示的ip地址,由网络号和主机号组成
* in:点分十进制转换成二进制后的结构体(网络字节序)
* return:成功返回0,失败返回-1,同时设置errno
*///返回ip地址in的网络号部分,返回值以主机字节序(小端)表示
in_addr_t inet_netof(struct in_addr in);//返回ip地址in的主机号部分,返回值以主机字节序表示
in_addr_t inet_lnaof(struct in_addr in);//生成一个IPv4地址,该地址由网络号和网络内的主机号组成
struct in_addr inet_makeaddr(in_addr_t net,in_addr_t host);

注:和 inet_aton 和 inet_pton 功能类似的函数还有 inet_addr但是不推荐使用,在某些情况下会出现 Bug,因此,本文章不作介绍。以下是上述函数的测试示例

int main(int argc, char const *argv[])
{printf("192.168.6.101的十六进制表示为 0x%X 0x%X 0x%X 0x%X\n",192,168,6,101);// 声明结构体接收数据struct sockaddr_in server_addr;struct in_addr server_in_addr;//将结构体里的值清0memset(&server_addr,0,sizeof(server_addr));memset(&server_in_addr,0,sizeof(server_in_addr));//出错返回-1,但是传入结构体的数据不是-1inet_aton("192.168.6.101",&server_in_addr);printf("inet_aton:0x%X\n",server_in_addr.s_addr);//万能方法  inet_ptoninet_pton(AF_INET,"192.168.6.101",&server_in_addr); printf("inet_pton:0x%X\n",server_in_addr.s_addr);//将结构体转换为字符串(主机字节序)printf("转化回字符串%s\n",inet_ntoa(server_in_addr));//本地网络地址(主机号)printf("本地网络地址:0x%X\n",inet_lnaof(server_in_addr));//网络号地址printf("网络号地址:0x%X\n",inet_netof(server_in_addr));//拼接为完整的ip地址server_addr.sin_addr = inet_makeaddr(inet_netof(server_in_addr),inet_lnaof(server_in_addr));printf("拼接后的ip地址:%s\n",inet_ntoa(server_addr.sin_addr));return 0;
}

2.5 INADDR_ANY

如果我们每次创建服务端套接字都要输 IP 地址会有些繁琐,此时可如下初始化地址信息。

struct sockaddr_in addr;
char*  serv_port = "9190";
memset(&sockaddr_in,0,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(atoi(serv_port));

利用 常数INADDR_ANY 分配服务器端 IP 地址,若采用这种方式,则可自动获取运行服务器端的计算机IP地址,不必亲自输入。而且,若同一计算机中已分配多个IP地址(多宿主计算机,一般路由器属于这一类),则只要端口号一致,就可以从不同IP地址接收数据。因此,服务器端中优先考虑这种方式。而客户端中除非带有一部分服务器端功能,否则不会采用。

2.6 Socket 编程相关函数

(1)创建套接字 Socket

int socket(int domain, int type, int protocol);
/**
* 创建一个新的Socket。
* domain:指定通信协议族,常使用的协议族如AF_INET(IPv4)或AF_INET6(IPv6)。
* type:指定Socket的类型,即数据传输的方式,
*       如字节流SOCK_STREAM(TCP)或数据段SOCK_DGRAM(UDP)。
* protocol:计算机通信中所使用的协议,通常为0,表示使用默认协议。
* return:成功返回int类型的Socket文件描述符,失败返回-1。
*/

(2)绑定地址 bind

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/**
* 将文件描述符sockfd绑定到一个地址addr
* sockfd:Socket描述符。
* addr:指向要绑定的地址结构的指针。
* addrlen:地址结构的长度。
* return:成功返回0,失败返回-1。
*/

(3)监听连接请求 listen   

int listen(int sockfd, int backlog);
/**
* 将sockfd所指向的套接字设置为即监听套接字
* sockfd:Socket描述符。
* backlog:等待连接队列的最大长度。
* return:成功返回0,失败返回-1。
*/

(4)接受连接请求 accept

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
/**
* 接受客户端的连接请求。从监听套接字sockfd的待处理连接队列中提取第一个连接请求,
* 创建一个新的连接套接字,并返回指向该套接字的新文件描述符
* 
* sockfd:Socket描述符。
* addr:用于存储 客户端地址信息 的结构体指针。
* addrlen:指向客户端地址结构体长度的指针
* return:成功返回一个新的Socket描述符,新的socket用来和服务端进行连接通信,失败返回-1。
*/

(5)发起连接请求 connect        

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/**
* 由客户端调用,来与服务器建立连接
* sockfd:Socket描述符。
* addr:指向服务器端地址结构的指针。
* addrlen:地址结构的长度。
* return:成功返回0,失败返回-1。
*/

(6)发送数据 send

size_t send(int sockfd, const void *buf, size_t len, int flags);
/**
* sockfd:Socket描述符。
* buf:发送缓冲区
* len:要发送的数据长度
* flags:传输控制标志,通常为0,表示不使用特殊行为
* return:功返回发送的字节数,失败返回-1,同时设置errno
*/

(7)接收数据 revc

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
/**
* sockfd:Socket描述符。
* buf:接收缓冲区
* len:接收缓冲区长度
* flags:传输控制标志,通常为0,表示不使用特殊行为
* return:成功返回收到的字节数,如果连接已经正常关闭,返回0
*         如果出现错误,返回-1,同时设置errno
*/

(8)关闭连接 shutdown

int shutdown(int sockfd,int how);
/**
* 关闭socket的一部分或全部连接
* sockfd:Socket描述符。
* how:指定关闭的类型,可以取值为:
* 					SHUT_RD:关闭读
* 					SHUT_WR:关闭写
* 					SHUT_RDWR:同时关闭读取和写入
* return:成功返回0,失败返回-1,同时设置errno
*/

(9)关闭连接 close

int close(int sockfd);
/**
* 终止一个套接字的连接(如果已连接上),然后关闭文件描述符,释放相关的资源。
* close是关闭数据传输的两个方向,之后进程将无法读/写入套接字。
* 
* sockfd:Socket描述符。
* return:成功返回0,失败返回-1,同时设置errno
*/

2.7 C标准中的 main 函数声明

在正式开始套接字编程之前,我们先简要了解一下 C 标准中的 main 函数声明。C 语言提供了以下两种 main 函数声明方式。

(1)无参形式

C99 标准之前,main 函数没有参数的形式被写成 int main()。从C99标准开始,推荐使用 int main(void) 明确指明 main 函数不接受任何参数,以提高代码的可读性和一致性。

int main(void) 
int main()

(2)有参形式

int main(int argc, char *argv[])
  • argc:传递给程序的命令行参数的数量

  • argv:指向字符串数组指针,存储了命令行参数

  • argv[0]:通常是程序名称

  • argv[1] 和 argv[argc-1] 是实际的命令行参数

2.8 套接字应用示例

以下应用示例是基于TCP协议进行通信,目前还未涉及TCP协议,因此,阅读代码时请重点关注套接字相关函数的调用过程,不必理解全部示例。

(1)服务器端 hello_server.c

#define handle_error(cmd,result)    \if(result < 0)                  \{                               \perror(cmd);                \return -1;                  \}                               \int main(int argc, char const *argv[])
{//服务端和客户端地址struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;memset(&serv_addr,0,sizeof(serv_addr));memset(&clnt_addr,0,sizeof(clnt_addr));char message[] = "Hello World";//命令行参数是否为两个if(argc != 2) {printf("Usage:%s <port>\n",argv[0]);exit(1);}//初始化IP地址serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(atoi(argv[1]));//INADDR_ANY 是一个宏,表示服务器监听所有可用的网络接口(即 0.0.0.0)//serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);   //写法一inet_pton(AF_INET,"0.0.0.0",&serv_addr.sin_addr);   //写法二//1、创建套接字int serv_sock = socket(AF_INET,SOCK_STREAM,0);handle_error("socket",serv_sock);//2、绑定地址int temp=bind(serv_sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr));handle_error("bind",temp);//3、监听temp = listen(serv_sock,128);handle_error("listen",temp);//4、接受连接socklen_t clnt_size = sizeof(clnt_addr);//注意accept的第三个参数是 指向服务端地址长度的指针//此处的文件描述符clnt_sock是用来向服务端进行通信的int clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_size);handle_error("accept",clnt_sock);printf("与客户端%s %d建立连接 文件描述符:%d\n",inet_ntoa(clnt_addr.sin_addr),ntohs(clnt_addr.sin_port),clnt_sock);//5、发送数据// write(clnt_sock,message,sizeof(message));int count = send(clnt_sock,message,1024,0);handle_error("send",count);//6、关闭套接字连接close(serv_sock);close(clnt_sock);return 0;
}

(2)客户端 hello_client.c

#define handle_error(cmd,result)    \if(result < 0)                  \{                               \perror(cmd);                \return -1;                  \}                               \int main(int argc, char const *argv[])
{struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;memset(&serv_addr,0,sizeof(serv_addr));memset(&clnt_addr,0,sizeof(clnt_addr));char *message = NULL;message = malloc(sizeof(char)*1024);if(argc != 3) {printf("Usage:%s <IP> <port>\n",argv[0]);exit(1);}serv_addr.sin_family = AF_INET; inet_pton(AF_INET,argv[1],&serv_addr.sin_addr); serv_addr.sin_port = htons(atoi(argv[2])); //客户端套接字通信流程int sock = socket(AF_INET,SOCK_STREAM,0);handle_error("socket",sock);int temp=connect(sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr));handle_error("connect",temp);printf("连上服务器端%s %d\n",inet_ntoa(serv_addr.sin_addr),ntohs(serv_addr.sin_port));//客户端不必像accept那样返回新的文件描述符,因此一直使用sock通信int str_len = recv(sock,message,1024,0);handle_error("recv",str_len);printf("Message from server:%s\n",message);close(sock);free(message);return 0;
}

(3)测试结果

127.0.0.1是回送地址(loopbackaddress),指的是计算机自身IP地址。因为本例当中服务器端和客户端在同一计算机中运行,因此,连接目标服务器端的地址为127.0.0.1。当然,若用实际IP地址代替此地址也能正常运转。如果服务器端和客户端分别在 2 台计算机中运行,则可以输人服务器端 IP 地址。

相关文章:

Linux 网络编程(二)——套接字编程简介

文章目录 2 Socket 套接字 2.1 什么是 Socket 2.2 Socket编程的基本操作 2.3 地址信息的表示 2.4 网络字节序和主机字节序的转换 2.4.1 字节序转换 2.4.2 网络地址初始化与分配 2.5 INADDR_ANY 2.6 Socket 编程相关函数 2.7 C标准中的 main 函数声明 2.8 套接字应用…...

串行通信 与 并行通信 对比

总目录 一、并行通信 1. 定义与核心特点 1&#xff09; 定义 并行通信是指通过多条数据线同时传输一组数据的各个位&#xff08;如8位、16位或更多&#xff09;&#xff0c;以字节或字为单位进行数据交换的通信方式。 2&#xff09;核心特点 特点描述传输速度快多位同时传…...

基于springboot+vue的北部湾地区助农平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...

Docker技术系列文章,第七篇——Docker 在 CI/CD 中的应用

在当今快速发展的软件开发领域&#xff0c;持续集成与持续部署&#xff08;CI/CD&#xff09;已经成为提高软件交付效率和质量的关键实践。而 Docker 作为一种流行的容器化技术&#xff0c;为 CI/CD 流程提供了强大的支持。通过将应用及其依赖项打包成容器&#xff0c;Docker 确…...

Hive SQL中 ?+.+ 的用法,字段剔除

一、含义 ?. 的用法代表剔除表中的特定字段&#xff0c;建议按照字段顺序列出以确保正确性。 二、参数设置 -- 首先需要设置一个参数&#xff1a; set hive.support.quoted.identifiersNone; --然后指定要剔除哪个字段 select (dateline)?. from test.dm_user_add三、举例…...

Vue学习笔记集--pnpm包管理器

pnpm包管理器 官网&#xff1a; https://www.pnpm.cn/ pnpm简介 pnpm全称是performant npm&#xff0c;意思为“高性能的npm”&#xff0c;它通过硬链接和符号链接共享依赖&#xff0c;提升安装速度并减少存储占用。 功能特点 节省磁盘空间&#xff1a;依赖包被存放在一个统…...

游戏交易系统设计与实现(代码+数据库+LW)

摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对游戏交易信息管理的提升&#x…...

为什么视频文件需要压缩?怎样压缩视频体积即小又清晰?

在日常生活中&#xff0c;无论是为了节省存储空间、便于分享还是提升上传速度&#xff0c;我们常常会遇到需要压缩视频的情况。本文将介绍为什么视频需要压缩&#xff0c;压缩视频的好处与坏处&#xff0c;并教你如何使用简鹿视频格式转换器轻松完成MP4视频文件的压缩。 为什么…...

腾讯pcg客户端一面

Java 基本引用类型 常见异常以及怎么处理 所有类的父类是什么&#xff0c;有哪些常用方法 常用线程池有哪些 线程池的创建参数 如何实现线程同步 常用锁有哪些 Lock和reentrantlock有什么不一样 Reentrantlock要手动释放锁吗 数据结构 数组和链表的区别 队列和栈的区别 为什么…...

解决vscode终端和本地终端python版本不一致的问题

&#x1f33f; 问题描述 本地终端&#xff1a; vscode终端&#xff1a; 别被这个给骗了&#xff0c;继续往下看&#xff1a; 难怪我导入一些包的时候老提示找不到&#xff0c;在本地终端就不会这样&#xff0c;于是我严重怀疑vscode中的python版本和终端不一样&#xff0c…...

常见几种网络攻击防御方式

xss跨站脚本攻击 反射型 XSS&#xff08;Reflected XSS&#xff09;&#xff1a; 恶意脚本是通过 URL 参数或者表单提交直接传递给服务器的&#xff0c;并且立即在响应页面中反射返回给用户。 假设有一个登录页面&#xff0c;用户可以通过 URL 参数传递一个消息&#xff1a; &…...

操作系统之输入输出

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

TCP/IP的网络连接设备

TCP/IP层物理层网卡、集线器、中继器数据链路层网桥、交换机网络层路由器传输层网关应用层 1.网桥&#xff1a;网桥主要功能是将一个网络的数据沿通信线路复制到另一个网络中去&#xff0c;可以有效的连接两个局域网 2.网关&#xff1a;网关又称协议转换器&#xff0c;是将两…...

记一次feign调用400,参数过长导致,修改解决

feign客户端PostMapping("/website/checkChooseColumn") boolean checkChooseColumn(RequestParam("chooseColumn") String chooseColumn);服务端 PostMapping("/checkChooseColumn") public boolean checkChooseColumn(RequestParam("cho…...

【大模型基础_毛玉仁】4.3 参数选择方法

目录 4.3 参数选择方法4.3.1 基于规则的方法4.3.2 基于学习的方法1&#xff09;公式&#xff1a;2&#xff09;Child-tuning 的两种变体模型3&#xff09;Child-tuning总结 4.3 参数选择方法 参数选择方法: 对预训练模型中部分参数微调&#xff0c;不添加额外参数以避免推理时…...

企业级Linux服务器初始化优化全流程

实战指南&#xff1a;企业级Linux服务器初始化优化全流程 本文基于某电商平台百万级并发服务器的真实调优案例整理&#xff0c;所有操作均在Rocky Linux8.5验证通过&#xff0c;不同发行版请注意命令差异 一、服务器安全加固&#xff08;Situation-Task-Action-Result&#xff…...

亿级分布式系统架构演进实战(十一)- 垂直拆分(服务治理体系、安全架构升级)

亿级分布式系统架构演进实战&#xff08;一&#xff09;- 总体概要 亿级分布式系统架构演进实战&#xff08;二&#xff09;- 横向扩展&#xff08;服务无状态化&#xff09; 亿级分布式系统架构演进实战&#xff08;三&#xff09;- 横向扩展&#xff08;数据库读写分离&#…...

飞速(FS)InfiniBand解决方案助力领先科技公司网络升级

国家&#xff1a;越南 行业&#xff1a;信息技术 网络类型&#xff1a;InfiniBand网络 方案类型&#xff1a;HPC网络 案例亮点 通过真实使用场景的全面测试&#xff0c;确保出色兼容性和高可用性&#xff0c;显著降低部署风险和运营成本。 借助飞速&#xff08;FS&#xf…...

[Qt5] QMetaObject::invokeMethod使用

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…...

深入理解垃圾收集算法:从分代理论到经典回收策略

垃圾收集&#xff08;Garbage Collection, GC&#xff09;是现代虚拟机自动内存管理的核心机制。它不仅能自动回收不再使用的对象&#xff0c;还能极大减轻开发者在内存管理上的负担。本文将详细讲解垃圾收集算法的基本思想、分代收集理论以及几种经典的垃圾收集算法。 注&…...

数据降维——PCA与LDA

特征选择和特征提取 特征选择和特征提取是数据降维的重要步骤。 1. 定义与目标 特征提取&#xff1a; 目标&#xff1a;通过变换&#xff08;如投影、编码&#xff09;将原始高维特征映射到新的低维空间&#xff0c;新特征是原始特征的组合&#xff08;线性或非线性&#xff…...

机器学习中的 K-均值聚类算法及其优缺点

K-均值聚类是一种常用的无监督学习算法&#xff0c;用于将数据集中的样本分为 K 个簇。其工作原理是通过迭代优化来确定簇的中心点&#xff0c;实现样本的聚类。 算法步骤如下&#xff1a; 随机选择 K 个样本作为初始簇中心。根据每个样本和簇中心的距离将样本归类到最近的簇…...

RAID原理

一、RAID 0 原理 ​核心特点​ ​条带化&#xff08;Striping&#xff09;​&#xff1a;数据被分割成块&#xff08;Block&#xff09;&#xff0c;交替写入多个磁盘​&#xff08;至少2块&#xff09;。​无冗余&#xff1a;不提供数据备份或校验&#xff0c;依赖所有磁盘同…...

2025系统分析师---软件工程:深度剖析常见软件开发方法

在软件工程这一复杂而精妙的领域中&#xff0c;软件开发方法的选择与实施无疑是项目成功的关键所在。作为一名资深软件技术专家&#xff0c;我深知不同的开发方法适用于不同的业务场景&#xff0c;各自具备独特的优缺点。本文将深入探讨几种常见的软件开发方法&#xff0c;包括…...

中文字符计数器,助力所有python对齐业务(DeepSeek代笔)

编码制式反推双宽&#xff0c;精准字宽库力推中文对齐。 笔记模板由python脚本于2025-03-26 23:49:24创建&#xff0c;本篇笔记适合为中文终端显示和文本输出对齐烦恼的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅…...

扫描注解指定路径

10.扫描注解 在 Spring Boot 中&#xff0c;EnableConfigurationProperties 和 ConfigurationPropertiesScan 是两个用于显式启用和管理 ConfigurationProperties 类的注解。它们提供了更灵活的方式来注册和扫描 ConfigurationProperties 类&#xff0c;尤其是在某些复杂场景或…...

像素到数据:Selenium,OpenCV,Tesseract,Python构建的智能解析系统

基于Selenium与OCR技术的网页信息智能提取方案 一、应用场景解析 在Web自动化测试和数据分析领域,经常需要处理动态渲染的网页信息,特别是当页面元素以图像形式呈现时。本文介绍的解决方案结合了浏览器自动化与图像识别技术,有效解决了以下典型场景: 动态渲染的可视化数据…...

徘徊检测:视觉分析技术的安防新方向

利用视觉分析的方式检测徘徊检测 背景 随着时代的发展&#xff0c;失业率上升导致社会不稳定因素增加&#xff0c;安保问题愈发突出。特别是在住宅区、工厂、办公园区等公共场所&#xff0c;对于徘徊人员的检测成为确保安全的关键一环。传统的安保手段如人工巡逻、监控录像回…...

CentOS 7 挂载与卸载文件系统

一、挂载文件系统​ 1. 查看系统磁盘与分区情况​ 在挂载文件系统之前&#xff0c;需要先了解系统中的磁盘和分区信息。使用fdisk -l命令&#xff0c;可列出所有磁盘和分区的详细信息&#xff0c;示例如下&#xff1a; [rootlocalhost ~]# fdisk -lDisk /dev/sda: 53.7 GB, …...

MySQL实战(尚硅谷)

要求 代码 # 准备数据 CREATE DATABASE IF NOT EXISTS company;USE company;CREATE TABLE IF NOT EXISTS employees(employee_id INT PRIMARY KEY,first_name VARCHAR(50),last_name VARCHAR(50),department_id INT );DESC employees;CREATE TABLE IF NOT EXISTS departments…...

JavaScript 改变 HTML 内容

JavaScript 改变 HTML 内容 JavaScript 改变 HTML 内容的核心在于通过 DOM&#xff08;文档对象模型&#xff09;操作实现动态更新&#xff0c;以下是主要方法及场景解析&#xff1a; 一、直接修改元素内容 1. innerHTML 属性 用于获取或设置元素的 HTML 内容&#xff08;包…...

第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(部分题解)

文章目录 前言日期统计题意&#xff1a; 冶炼金属题意&#xff1a; 岛屿个数题意&#xff1a; 子串简写题意&#xff1a; 整数删除题意&#xff1a; 总结 前言 一年一度的&#x1f3c0;杯马上就要开始了&#xff0c;为了取得更好的成绩&#xff0c;好名字写了下前年2023年蓝桥…...

机器学习——Bagging、随机森林

相比于Boosting的集成学习框架&#xff0c;Bagging(Bootstrap Sampling&#xff0c;自助聚集法&#xff0c;又称为自助采样)作为一种自助聚集且并行化的集成学习方法&#xff0c;其通过组合多个基学习器的预测结果来提高模型的稳定性和泛化能力。其中随机森林是Bagging学习框架…...

数据库——MySQL基础操作

一、表结构与初始数据 假设存在以下两张表&#xff1a; 1. student 表 字段名数据类型描述idINT学生唯一标识符nameVARCHAR(100)学生姓名ageINT学生年龄sexVARCHAR(10)学生性别 初始数据&#xff1a; idnameagesex1张三20男2李四22女3王五21男 2. course 表 字段名数据类…...

存储过程、存储函数与触发器详解(MySQL 案例)

存储过程、存储函数与触发器详解&#xff08;MySQL 案例&#xff09; 一、存储过程&#xff08;Stored Procedure&#xff09; 定义 存储过程是预先编译好并存储在数据库中的一段 SQL 代码集合&#xff0c;可以接收参数、执行逻辑操作&#xff08;如条件判断、循环&#xff09;…...

2025年注册安全工程师考试练习题

注册安全工程师练习题&#xff0c;涵盖了不同的知识点和题型&#xff1a; 单选题 某机械制造企业委托具有相应资质的中介服务机构的专业技术人员为其提供安全生产管理服务。依据《安全生产法》&#xff0c;保证该企业安全生产的责任由&#xff08; &#xff09;负责。 A. 专业…...

Photoshop 2025安装包下载及Photoshop 2025详细图文安装教程

文章目录 前言一、Photoshop 2025安装包下载二、Photoshop 2025安装教程1.解压安装包2.运行程序3.修改安装路径4.设安装目录5.开始安装6.等安装完成7.关闭安装向导8.启动软件9.安装完成 前言 无论你是专业设计师&#xff0c;还是初涉图像处理的小白&#xff0c;Photoshop 2025…...

ESP32通过WiFi获取网络时间(NTP)

代码部分 代码由station_example_main的官方例程修改 /* WiFi station ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS&…...

docker使用命令笔记

docker使用命令笔记 1. 安装docker2. 拉取镜像3. 镜像与容器4. 基于镜像创建容器4. 操作创建好的容器5. docker文件传输6. ubuntu的docker的一些基本环境搭建 记录docker的一些使用命令 1. 安装docker 遵循官方安装说明即可&#xff0c;windows需要下载docker desktop后在doc…...

关于服务器只能访问localhost:8111地址,局域网不能访问的问题

一、问题来源&#xff1a; 服务器是使用的阿里云的服务器&#xff0c;服务器端的8111端口没有设置任何别的限制&#xff0c;但是在阿里云服务器端并没有设置相应的tcp连接8111端口。 二、解决办法&#xff1a; 1、使用阿里云初始化好的端口&#xff1b;2、配置新的阿里云端口…...

触发器及报警

一、触发器介绍 Trigger 作用&#xff1a;报警 触发某一个监控项状态的变化 基于监控项创建 一个监控项可以有多个触发器 1、创建触发器语法 {<server>:<key>.<function>(<parameter>)}<operator><constant> {被监控主机:键值.函数…...

如何用 Postman 发送 GET 请求?详解

Postman 是一款广泛用于 API 开发和测试的工具&#xff0c;通过它&#xff0c;我们可以轻松地发送 GET 请求。首先&#xff0c;需要新建接口并设置为 GET 请求&#xff0c;然后填写相关的 URL 地址和参数&#xff0c;最后点击“Send”按钮即可发起请求。 Postman 如何发送 get…...

主流软件工程模型全景剖析

一、瀑布模型 阶段划分 需求分析&#xff1a;与用户深入沟通&#xff0c;全面了解软件的功能、性能、可靠性等要求&#xff0c;形成详细的需求规格说明书。设计阶段&#xff1a;包括总体设计和详细设计。总体设计确定软件的体系结构&#xff0c;如模块划分、模块之间的接口等&…...

NVMe协议

一、NVMe 的诞生背景 ​传统协议瓶颈&#xff1a; 早期的SATA接口SSD使用 ​AHCI协议&#xff0c;设计初衷是适配机械硬盘&#xff08;HDD&#xff09;&#xff0c;其单队列、高延迟的特性无法发挥SSD的高速性能。​PCIe接口的潜力&#xff1a; NVMe专为 ​PCIe接口的SSD​ 设…...

开关磁阻电机类型及其控制技术

开关磁阻电机( Switched Reluctance Motors,SRM) 具有结构简单、坚固、成本低、 工作可靠、控制灵活、运行效率高&#xff0c;适于高速与恶劣环境运行等优点, 由其构成的传动系统( Switched Reluctance Drives, SRD) 具有交、直流传动系统所没有的优点, 为此&#xff0c;世界各…...

CMake 构建的Qt 项目中的构建套件的配置

在Qt 框架中&#xff0c;使用CMake 构建工具时&#xff0c;需要自己给构建套件添加相关配置&#xff0c;否则已经添加的构建套件将不可选择使用。 创建CMake 项目后&#xff0c;如果打开项目配置时&#xff0c;出现如下构建套件不可选的情况&#xff0c; 需要先确认是否安装…...

程序化广告行业(34/89):移动端特色广告与创意策略探秘

程序化广告行业&#xff08;34/89&#xff09;&#xff1a;移动端特色广告与创意策略探秘 大家好&#xff01;在程序化广告的学习之旅中&#xff0c;每一次探索都像是发现了新大陆。今天&#xff0c;我依旧怀揣着和大家共同进步的想法&#xff0c;来和大家深入聊聊程序化广告行…...

IT行业项目管理风险规避策略

在IT项目中,前端、后端、测试等不同角色的协同工作会带来各种项目管理风险。以下是针对这些风险的规避策略: 一、跨职能团队协作风险 1. 沟通不畅风险 解决方案: 建立每日站会机制(15分钟以内)使用协作工具(如Jira、飞书、钉钉)制定明确的接口文档标准(Swagger/YAPI)…...

24届非科班硕士入职做上位机开发,后续往工业软件还是音视频、后端发展?

今天给大家分享的是一位粉丝的提问&#xff0c;24届非科班硕士入职做上位机开发&#xff0c;后续往工业软件还是音视频、后端发展&#xff1f; 接下来把粉丝的具体提问和我的回复分享给大家&#xff0c;希望也能给一些类似情况的小伙伴一些启发和帮助。 同学提问&#xff1a; …...

Hadoop三 分布式sql计算hive入门

一 分布式SQL计算 对数据进行统计分析&#xff0c;SQL是目前最为方便的编程工具。 大数据体系中充斥着非常多的统计分析场景&#xff0c;所以&#xff0c;使用SQL去处理数据&#xff0c;在大数据中也是有极大的需求的。MapReduce支持程序开发&#xff08;Java、Python等&#…...