6 网络

6 网络

  • 1、概念
  • 2 IP地址
  • 3、套接字
  • 4、TCP协议
    • 4.1 TCP协议的基本特征
    • 4.2 建立连接
    • 4.4 终止连接
    • 4.5 编程模型
  • 5、UDP协议
    • 5.1 UDP协议的基本特性
    • 5.2 常用函数
    • 5.3 UDP通信模型
  • 6、域名解析

1、概念

计算机网络是实现资源共享和信息传递的计算机系统
ISO/OSI网络协议模型
在这里插入图片描述

TCP/IP协议
在这里插入图片描述

·应用程序负责组织的通常都是与业务相关的数据内容,而要想把这些数据内容通过网络发送出去,就要将其自上向下地压入协议栈,每经历一个协议层,就会对数据做一层封包,每一层输出的封包都是下一层输入的内容,消息包沿着协议栈的运动形成了消息流。
·当从网络上接收数据时,过程刚好相反,消息包自下向上地流经协议栈,每经历一个协议层,就会对输入的数据解一层封包,经过层层解包以后,应用程序最终得到的将只是与业务相关的数据内容

2 IP地址

  • 什么是P地址?
    IP地址,是IP协议提供的一种统一的地址格式,为互联网上的每个网络和每台主机分配一个逻辑地址,借以消除物理地址所带来的差异性
  • IP地址如何表示?
    在计算机内部,IP地址用一个32位无符号整数表示,如:0x01020304。
    人们更习惯使用点分十进制字符串表示,如:1.2.3.4。字符串形式的从左到右,对应整数形式的从高字节到低字节。注意这里所说的高低指的是数位高低而非地址高低
  • 什么是IP地址分级?
    A级地址:以0为首的8位网络地址+24位本地地址
    B级地址:以10为首的16位网络地址+16位本地地址
    C级地址:以110为首的24位网络地址+8位本地地址
    D级地址:以1110为首的32位多播地址
    例如:某台计算机的IP地址:192.168.182.48,写成整数形式:11000000 10101000 10110110 00110000
    代表的是C级地址,网络地址:192.168.182.0,本地地址:48
  • 子网掩码
    • 借助子网掩码可以快速帮助我们区定IP地址的网络地址和本地地址
      • 以IP地址:192.168.182.48,子网掩码:255.255.255.0为例
        网络地址=IP地址&子网掩码
        192.168.182.48 & 255.255.255.0 = 192.168.182.0
        本地地址=IP地址&~子网掩码
        192.168.182.48 & 0.0.0.255 = 0.0.0.48

3、套接字

在这里插入图片描述

套接字代表着主机的通信能力
套接字接口库规定在网络传输过程中采用网络字节序,也就是大端字节序,
而本机数据可能是小短字节序
- 小端字节序:数据的低位存放在低地址
- 大端字节序:数据的低位存放在高地址

4、TCP协议

TCP提供客户机与服务器的连接

4.1 TCP协议的基本特征

一个完整TCP通信过程需要依次经历三个阶段

  • 首先,客户机必须建立与服务器的连接
  • 然后,凭借已建立好的连接,通信双方相互交换数据
  • 最后,客户机与服务器双双终止连接,结束通信过程
    TCP保证数据传输的可靠性
  • TCP的协议栈底层在向另一端发送数据时,会要求对方在一个给定的时间窗口内返回确认。如果超过了这个时间窗口仍没有收到确认,则TCP会重传数据并等待更长的时间。只有在数次重传均告失败以后,TCP才会最终放弃。TCP含有用于动态估算数据往返时间(Round-Trip Time,RTT)的算法,因此它知道等待一个确认需要多长时间
    TCP保证数据传输的有序性
  • TCP的协议栈底层在向另一端发送数据时,会为所发送数据的每个字节指定一个序列号。即使这些数据字节没有能够按照发送时的顺序到达接收方,接收方的TCP也可以根据它们的序列号重新排序,再把最后的结果交给应用程序
    TCP是全双工的
  • 在给定的连接上,应用程序在任何时候都既可以发送数据也可以接收数据。因此,TCP必须跟踪每个方向上数据流的状态信息,如序列号和通告窗口的大小

4.2 建立连接

三路握手

  • 客户机的TCP协议栈向服务器发送一个SYN分节,告知对方自己将在连接中发送数据的初始序列号
  • 服务器的TCP协议栈向客户机发送一个单个分节,其中不仅包括对客户机SYN分节的ACK应答,还包含服务器自己的SYN分节,以告知对方自己在同一连接中发送数据的初始序列号
  • 客户机的TCP协议栈向服务返回ACK应答,以表示对服务器所发SYN的确认
    在这里插入图片描述

tcp包头结构,有20个字节,其中2个字节的源端口、2个字节的目的端口、4字节的序号、4字节的确认号等等共计20个字节的数据
在这里插入图片描述

三次握手的解释:
① 客户机首先向服务器发送数据包,数据包中的SYN的比特位是1,并且在序号位置指定一个数字,假定为100
② 服务器收到客户机发来的数据包,其中SYN的比特位是1,那么服务器就会应答一个数据包,数据包里的ACK比特位置1,代表一种应答,并且在确认号这里会将收到的序号+1,这里是101,代表服务器真的收到了客户机的数据包,然后将序号指定一个数字假定是200,并且将SYN比特位置1,一起发送给客户机
③ 客户机收到服务器发来的数据包,首先检查数据包中的ACK和确认号是否正确,然后会向服务器应答一个数据包,其中ACK比特位置1,代表是对服务器的应答,确认号填写收到的序号+1,这里是201,发送给服务器,代表客户机真的收到了服务器的数据包
④ 服务器收到数据包,检查ACK和确认号,至此连接建立

接口## 4.3 交换数据

  • 一旦连接建立,客户机即可构造请求包并发往服务器,服务器接收并处理来自客户机的请求包,构造响应包
  • 服务器向客户机发送响应包,同时捎带对客户机请求包的ACK应答。
  • 客户机接收来自服务器的响应包,同时向对方发送ACK应答
    在这里插入图片描述

4.4 终止连接

四次挥手

  • 客户机或者服务器主动关闭连接,TCP协议栈向对方发送FIN分节,表示数据通信结束。如果此时尚有数据滞留于发送缓冲区中,则FIN分节跟在所有未发送数据之后
  • 接收到FIN分节的另一端执行被动关闭,-方面通过TCP协议栈向对方发送ACK应答,另一方面向应用程序传递文件结束符
  • 一段时间以后,方才接收到FIN分节的进程关闭自己的连接,同时通过TCP协议栈向对方发送FIN分节
  • 对方在收到FIN分节后发送ACK应答
    四次挥手的解释
    ① 客户机关闭套接字之后,客户机首先向服务器发送一个数据包,其中FIN比特位置1
    ② 服务器收到客户机发来的数据包,其中FIN比特位为1,向客户机回传一个应答,其中ACK置1
    ③ 服务器关闭对应的套接字操作之后,服务器向客户机发送一个数据包,其中FIN比特位置1
    ④ 客户机收到服务器发来的数据包,其中的FIN比特位为1,向服务器回传一个应答,其中ACK置1
    ⑤ 至此连接断开,通信终止

4.5 编程模型

在这里插入图片描述

  • 相关函数
    1:socket 创建套接字
// 头文件 sys/socket.h
int socket(int domain,int type,int protocol);
- 功能:创建套接字
- 参数:- domain:通信域,协议族,可取以下值:PF_LOCAL/PF_UNIX - 本地套接字,进程间通信PF_INET - 基于IPV4的网络通信PF_INET6 - 基于IPv6的网络通信PF_PACKET - 基于底层包的网络通信- type:套接字类型,可取以下值:SOCK_STREAM - 流式套接字,基于TCP协议SOCK_DGRAM - 数据报套接字,基于UDP协议SOCK_RAW - 原始套接字,工作在传输层以下- protocol:特殊协议,对于流式和数据报套接字而言,只能取0
- 返回值:成功返回表示套接字对象的文件描述符,失败返回-1

2:相关结构体

/*套接字接口库通过地址结构定位一个通信主体,可以是一个文件,可以是一台远程主机,也可以是执行者自己 */
// 基本地址结构,本身没有实际意义,仅用于泛型化参数
struct sockaddr{sa_family_t sa_family; // 地址族char sa_data\[14\]; // 地址值
}
// 本地地址结构,用于AF_LOCAL/AF_UNIX域的本地通信
struct sockaddr_un{sa_family_t sun_family;// 地址族(AF_LOCAL/AF_UNIX)char sun_path\[\];// 本地套接字文件的路径
}
// 网络地址结构,用于AF_INET域的IPV4写径通信
struct sockaddr_in{sa_family_t sin_family;∥地址族(AF_INET)in_port_t sin_port; //端口号(0~65535) - unsigned shortstruct in_addr sin_addr;//IP地址 - unsigned int
}
// 网络地址结构,用于AF_INET域的IPV4网络通信
struct in_addr{in_addr_t s_addr;
}
typedef uint16_t in_port_t; //无符号16位整数
typedef uint32_t in_addr_t; //无符号32位整数

3:字节序转换函数

uint32_t htonl(uint32_t hostlong); //长整形主机字节序到网络字节序
uint32_t ntohl(uint32_t netllong); //长整形网络字节序到主机字节序
uint16_t htons(uint16_t hostshort); //短整形主机字节序到网络字节序
uint16_t ntohs(uint16_t netshort); //短整型网络字节序到主机字节序
in_addr_t inet_addr(char const* ip); // 点分十进制字符串地址 -> 网络字节序形式整数地址
int inet_aton(char const* ip,struct in_addr* nip); //点分十进制字符串地址 -> 网络字节序形式整数地址
char* inet_ntoa(struct in_addr nip); //网络字节序形式整数地址 -> 点分十进制字符串地址

4:bind 将套接字和本机的地址结构绑定在一起

// 头文件 sys/socket.h
int bind(int sockfd,struct sockaddr const* addr,socklen_t addrlen);
- 功能:将套接字和本机的地址结构绑定在一起
- 参数:- sockfd:套接字描述符。- addr:自己的地址结构。- addrlen:地址结构的字节数
- 返回值:成功返回0,失败返回-1

5:listen 启动侦听

// 头文件 sys/socket.h
int listen(int sockfd,int backlog)
- 功能:启动侦听:在指定套接字上启动对连接请求的侦听功能
- 参数:- sockfd:套接字描述符,在调用此函数之前是一个主动套接字,是不能感知连接请求的,在调用此函数并成功返回之后,是一个被动套接字,具有感知连接请求的能力。- backlog:未决连接请求队列的最大长度,一般取不小于1024的值。
- 返回值:成功返回0,失败返回-1

6:accept

// 头文件 sys/socket.h
int accept(int sockfd,struct sockaddr* addr,socklen_t* addrlen);
- 功能:等待并接受连接请求,在指定套接字上阻塞,直到连接建立完成。
- 参数:- sockfd:侦听套接字描述符- addr:输出连接请求发起方的地址信息- addrlen:输出连接请求发起方的地址信息字节数
- 返回值:成功返回可用于后续通信的连接套接字描述符,失败返回-1
  • 案例
// tcp 服务器
#include <stdio.h>
#include <ctype.h> // toupper
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/socket.h> // 网络相关
#include <sys/types.h>// 网络相关
#include <arpa/inet.h>// 网络相关
#include <sys/wait.h>// 收尸
void sigfun(int signum){printf("服务器:收尸\n");for(;;){pid_t pid = waitpid(-1,NULL,WNOHANG);if(pid == -1){if(errno == ECHILD){printf("没有子进程了\n");break;}else{perror("waitpid");return ;}}else if(pid == 0){printf("%d进程在运行\n",getpid());break;}else{printf("%d进程:回收了%d进程的僵尸\n",getpid(),pid);}}
}int main(){printf("服务器设置信号量\n");if(signal(SIGCHLD,sigfun)==SIG_ERR){ // 对17号信号做捕获处理perror("signal");return -1;}printf("服务器:创建套接字\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");return -1;}printf("服务器:组织地址结构\n");struct sockaddr_in ser;// IPV4的网络地址结构ser.sin_family = AF_INET;ser.sin_port = htons(8980);// 端口号,这里需要做字节序转换,因为TCP协议栈需要这个端口ser.sin_addr.s_addr = inet_addr("192.168.174.152");printf("服务器:绑定套接字和地址结构\n");if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser)) == -1){perror("bind");return -1;}printf("服务器:启动侦听\n");if(listen(sockfd,1024)==-1){// 监听,用于接收客户端的连接请求(3次握手)perror("listen");return -1;}for(;;){printf("服务器:等待连接\n");struct sockaddr_in cli; //用于输出客户端的地址结构socklen_t len = sizeof(cli); // 用来输出地址结构的大小int conn = accept(sockfd,(struct sockaddr*)&cli,&len); // 用于完成与客户端的3次握手中的后两次if(conn == -1){ // conn 是用来和客户端通信用的,每接入一个客户端,就会生成一个新的connperror("accept");return -1;}printf("服务器:接收到%s:%hu的客户端的连接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));printf("服务器:业务处理\n");pid_t pid = fork();if(pid == -1){perror("fork");return -1;}if(pid == 0){close(sockfd);// 关掉从父进程复制过来的通信套接字for(;;){// 接收客户端发送的小写的串char buf[64]={};ssize_t size = read(conn,buf,sizeof(buf)-1);if(size == -1){perror("read");close(conn);return -1;}//客户端断开连接时if(size == 0){break;}// 转大写for(int i=0;i<strlen(buf);i++){buf[i]=toupper(buf[i]);}// 将大写的串回传给客户端if(write(conn,buf,strlen(buf))==-1){perror("write");close(conn);return -1;}}printf("服务器:关闭通信套接字\n");close(conn);return 0;}close(conn);// 子进程已经复制了这个套接字,父进程自己的直接关掉即可}printf("关闭服务器\n");close(sockfd);return 0;
}

7:connect 将套接字和对方的地址结构连接在一起

// 头文件 sys/socket.h
int connect(int sockfd,struct sockaddr const* addr,socklen_t addrlen);
- 功能:将套接字和对方的地址结构连接在一起
- 参数:- sockfd:套接字描述符- addr:对方的地址结构- addrlen:地址结构的字节数
- 返回值:成功返回0,失败返回-1

8:send 发送数据

// 头文件 sys/socket.h
ssize_t send(int sockfd,void const* buf,size_t count,int flags);
- 功能:发送数据
- 参数:- 若flags取0则与write函数完全等价,另外也可取以下值:MSG_DONTWAIT - 以非阻塞方式接收数据。MSG_OOB - 接收带外数据。MSG_DONTROUTE - 不查路由表,直接在本地网络中寻找目的主机
- 返回值:成功返回实际发送的字节数,失败返回-1

9:recv 接收数据

// 头文件 sys/socket.h
ssize_t recv(int sockfd,void* buf,size_t count,int flags);
- 功能:接收数据
- 参数:- 若flags取0则与read函数完全等价,另外也可取以下值:MSG_DONTWAIT - 以非阻塞方式接收数据。MSG_OOB - 接收带外数据。MSG_WAITALL - 等待所有数据,即不接收到count字节就不返回。
- 返回值:成功返回实际接收到的字节数,失败返回-1
  • 案例
// 基于tcp客户端的连接
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>int main(){printf("客户端:创建套接字\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");return -1;}printf("客户端:组织服务器的地址结构\n");struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(8980);ser.sin_addr.s_addr = inet_addr("192.168.174.152");printf("客户端:发起连接\n");if(connect(sockfd,(struct sockaddr*)&ser,sizeof(ser))==-1){perror("connect");return -1;}printf("客户端:业务处理\n");for(;;){// 发送小写的串char buf[64]={};fgets(buf,sizeof(buf),stdin);if(strcmp(buf,"!\n")==0){break;}if(send(sockfd,buf,strlen(buf),0)==-1){perror("send");return -1;}// 接收大写的串if(recv(sockfd,buf,sizeof(buf)-1,0)==-1){perror("recv");return -1;}// 显示printf("%s",buf);}printf("客户端:关闭套接字\n");close(sockfd);return 0;
}

5、UDP协议

5.1 UDP协议的基本特性

  • UDP不提供客户机与服务器的连接
    • UDP的客户机与服务器不必存在长期关系。一个UDP的客户机在通过一个套接字向一个UDP服务器发送了一个数据报之后,马上可以通过同一个套接字向另一个UDP服务器发送另一个数据报。同样,一个UDP服务器也可以通过同一个套接字接收来自不同客户机的数据报
  • UDP不保证数据传输的可靠性和有序性
    • UDP的协议栈底层不提供诸如确认、超时重传、RTT估算以及序列号等机制。因此UDP数据报在网络传输的过程中,可能丢失,也可能重复,甚至重新排序。应用程序必须自己处理这些情况
  • UDP不提供流量控制
    • UDP的协议栈底层只是一味地按照发送方的速率发送数据,全然不顾接收方的缓冲区是否装得下
  • UDP是全双工的
    • 在一个UDP套接字上,应用程序在任何时候都既可以发送数据也可以接收数据

5.2 常用函数

1:recvfrom 从哪里接收数据

// 头文件 sys/socket.h
ssize_t recvfrom(int sockfd,void* buf,size_t count,int flags,struct sockaddr* src_addr,socklen_t* addrlen);
- 功能:从哪里接收数据
- 参数:- 前四个参数和函数recv相同- src_addr:输出源主机的地址信息- addrlen:输入输出源主机的地址信息的字节数。
- 返回值:成功返回实际接收的字节数,失败返回-1

2:sendto 发送数据到哪里

// 头文件 sys/socket.h
ssize_t sendto(int sockfd,void const* buf,size_t count,int flags,struct sockaddr const* dest_addr,socklen_t addrlen);
- 功能:发送数据到哪里
- 参数:- 前四个参数和函数send相同- dest_addr:目的主机的地址信息。- addrlen:目的主机的地址信息的字节数。
- 返回值:成功返回实际发送的字节数,失败返回-1

5.3 UDP通信模型

在这里插入图片描述

  • 服务器
// udp 服务器
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys//types.h>
#include <arpa/inet.h>int main(){printf("服务器:创建套接字\n");int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd == -1){perror("socket");return -1;}printf("服务器:组织地址结构\n");struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(8090);ser.sin_addr.s_addr=inet_addr("192.168.174.152");printf("服务器:绑定套接字和地址结构\n");if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser))==-1){perror("bind");return -1;}printf("服务器:业务处理\n");for(;;){char buf[64]={};struct sockaddr_in cli;socklen_t len = sizeof(cli);if(recvfrom(sockfd,buf,sizeof(buf)-1,0,(struct sockaddr*)&cli,&len)==-1){perror("recvfrom");return -1;}// 转大写for(int i=0;i<strlen(buf);i++){buf[i] = toupper(buf[i]);}// 将大写的串回传到客户端if(sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*) &cli,len) == -1){perror("sendto");return -1;}}printf("服务器关闭套接字\n");close(sockfd);return 0;
}
  • 客户端
// UDP客户端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main(){printf("客户端:创建套接字\n");int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd == -1){perror("socker");return -1;}        printf("客户端:组织服务器地址结构\n");struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(8090);ser.sin_addr.s_addr = inet_addr("192.168.174.152");printf("客户端:业务处理\n");for(;;){// 向客户端发送小写的串char buf[64] = {};fgets(buf,sizeof(buf),stdin);if(strcmp(buf,"!\n")==0){break;}if(sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser,sizeof(ser))==-1){perror("sendto");return -1;}// 接收服务器回传if(recv(sockfd,buf,sizeof(buf)-1,0)==-1){perror("recv");return -1;}// 显示printf("客户端:收到%s",buf);}// 关闭套接字close(sockfd);return 0;
}

6、域名解析

  • IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替1P地址标识站点地址
  • 域名解析就是域名到IP地址的转换过程。域名的解析工作由DNS服务器完成
  • 当应用过程需要将一个主机域名映P地址时,就调用域名解析函数,解析函数将待转换的域名放在DNS请求中,以UDP报文方式发给本地域名服务器。本地的域名服务器查到域名后,将对应的IP地址放在应答报文中返回。
    相关函数
    gethostbyname 获取主机信息
// 头文件 netdb.h
struct hostent* gethostbyname(char const* host_name);
- 功能:通过参数所传的主机域名,获取主机信息
- 参数:- host_name 主机域名
- 返回值:函数执行成功返回表示主机信息的结构体指针,失败返回NULL
- 注意,该函数需要再联网情况下使用

结构

struct hostent{char *h_name; //主机官方名char **h_aliases; //主机别名表int h_addrtype; //地址类型int h_length; //地址长度char **h_addr_list; //IP地址表
};
  • 案例
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc,char* argv[]){struct hostent* h = gethostbyname(argv[1]);if(h==NULL){perror("gethostbyname");return -1;}printf("主机官方名\n");printf("\t%s\n",h->h_name);printf("主机别名\n");for(char **pp = h->h_aliases;*pp;pp++){printf("\t%s\n",*pp);}printf("IP地址表\n");for(struct in_addr **pp=(struct in_addr**)h->h_addr_list;*pp;pp++){printf("\t%s\n",inet_ntoa(**pp));}return 0;
}
  • 创建http请求发送
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>int main(){// 创建套接字int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");return -1;}// 组织百度服务器的地址结构struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(80);ser.sin_addr.s_addr = inet_addr("36.155.132.76");// 向百度服务器发起连接if(connect(sockfd,(struct sockaddr*)&ser,sizeof(ser))==-1){perror("connect");return -1;}// 组织http请求并发送给百度服务器char request[1024] ={};sprintf(request,"GET / HTTP/1.1\r\n""Host: www.baidu.com\r\n""Accept: */*\r\n""Connection: close\r\n\r\n");if(send(sockfd,request,strlen(request),0)==-1){perror("send");return -1;}// 接收百度服务器回传的响应for(;;){char respond[1024] = {};ssize_t size = recv(sockfd,respond,sizeof(respond)-1,0);if(size == -1){perror("recv");return -1;}if(size == 0){break;}printf("%s",respond);}printf("\n");close(sockfd);return 0;
}

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

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

相关文章

C语言进阶 10. 字符串

C语言进阶 10. 字符串 文章目录 C语言进阶 10. 字符串10.1. 字符串10.2. 字符串变量10.3. 字符串输入输出10.4. 字符串数组10.5. 单字符输入输出10.6. 字符串函数strlen()10.7. 字符串函数strc()10.8. 字符串函数strcpy()10.9. 字符串搜索函数10.10. PAT10-0. 说反话 (20)10-1.…

idea中导入外部依赖并打包到jar包中

前言&#xff1a; 很多时候在我们写项目对接三方的时候都需要导入三方jar包&#xff0c;而这时候我们用平常的pom里面写依赖发现导入不了&#xff08;直接把jar包放在本地导入的话打包的话也不会将该依赖打包进我们项目的jar包&#xff09;&#xff0c;我在网上找了几种方法 …

Linux网络-ss命令

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器&#xff0c;主要的作用就是向客户端提供网络…

【C++】C++11中R字符串的作用

在 C11 中添加了定义原始字符串的字面量 1.定义和基本使用 定义方式为&#xff1a; R"xxx(原始字符串)xxx"其中 () 两边的字符串可以省略&#xff0c;R只会处理括号中的字符串。 原始字面量 R 可以直接表示字符串的实际含义&#xff0c;而不需要额外对字符串做转义…

谷歌团队新技术Alchemist:使用扩散模型对材料属性进行参数控制

Alchemist是由谷歌团队和麻省理工学院联合研发的一项创新技术&#xff0c;它利用扩散模型对材料属性进行精细的参数控制。这项技术的核心在于能够对真实图像中的物体材料属性进行调整&#xff0c;包括粗糙度、金属感、反照率和透明度等。Alchemist的实现依赖于先进的文本到图像…

【时时三省】(C语言基础)循环语句while(2)

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ——csdn时时三省 getchar和scanf的作用 示例: int main ( ) &#xff5b; char password[20] ( 0 ) ; printf ( "请输入密码&#xff1a;> " )&#xff1b; scanf ( " &#xff05;s…

Sping项目只能勾选17和21 (已解决) 导致的后续Invalid bound statement (not found):

问题发现 今天创建项目的时候发现 idea初始化spring的时候选择不了Java8 解决方案:替换URL为 https://start.aliyun.com/ 将IDEA页面创建Spring项目&#xff0c;其实是访问spring initializr去创建项目。故我们可以通过阿里云国服去间接创建Spring项目。 将https://start.spr…

使用 VMware vCenter Server(vSphere Client)迁移 ESXi 虚拟机

我需要将虚拟机 k8s-dev-node4从 ESXi 主机 192.168.1.161 迁移到 ESXi 主机 192.168.1.162 上&#xff0c;使用 VMware vCenter Server&#xff08;vSphere Client&#xff09;在浏览器上可视化操作&#xff0c;将这个需求变的非常简单。 1、选中需要迁移的虚拟机&#xff0c…

【AI落地应用实战】Amazon Bedrock +Amazon Step Functions实现链式提示(Prompt Chaining)

一、链式提示 Prompt Chaining架构 Prompt Chaining 是一种在生成式人工智能&#xff08;如大型语言模型&#xff09;中广泛使用的技术&#xff0c;它允许用户通过一系列精心设计的提示&#xff08;Prompts&#xff09;来引导模型生成更加精确、丰富且符合特定需求的内容。 P…

获取手机当前信号强度(dbm/asu值)解决 getGsmSignalStrength()总是返回99问题

能看到这篇文章说明网上哪些获取 &#xff08;dbm/asu值&#xff09;不适合你&#xff0c;不是他们的代码不正确&#xff0c;而是不符合你的情况 比如安卓6获取android手机信号强度 可以看这篇文章 https://blog.csdn.net/sinat_31057219/article/details/81134030 当然如果你…

Javaweb项目|springboot医院管理系统

收藏点赞不迷路 关注作者有好处 文末获取源码 一、系统展示 二、万字文档展示 基于springboot医院管理系统 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringSpringMVCMyBatisVue 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 编号&#xff1a;…

Source insight 配置代码格式化

代码格式化工具&#xff1a;Artistic Style Files Download 配置 Source Insight 添加 Astyle 命令 Tools --> Custom Commands -->Add 在 Run 栏填入格式化命令&#xff1a; "D:\Program Files\astyle-3.5.2-x64\astyle.exe" -A3 -t -xV -w -Y -m0 -p -H …

【Vulnhub系列】Vulnhub_Raven2靶场渗透(原创)

【Vulnhub系列靶场】Vulnhub_Raven2 渗透 原文转载已经过授权 原文链接&#xff1a;Lusen的小窝 - 学无止尽&#xff0c;不进则退 (lusensec.github.io) 一、环境准备 从网盘下载该靶机&#xff0c;在vm中选择【打开】 然后设置好存储路径&#xff0c;开机后检查靶机的网络连…

Redis缓存数据库进阶——Redis缓存数据同步问题(8)

Redis缓存使用问题 数据一致性 只要使用到缓存&#xff0c;无论是本地内存做缓存还是使用 redis 做缓存&#xff0c;那么就会存在数据同步的问题。 我以 Tomcat 向 MySQL 中写入和删改数据为例&#xff0c;来给你解释一下&#xff0c;数据的增删改操作具体是如何进行的。 我…

从入门到精通:电商设计师的职业发展指南

在当今数字时代&#xff0c;电商设计师的作用越来越重要。从电子商务网站的整体造型设计到产品页面的具体布局&#xff0c;他们的工作范围是电子商务企业成功的关键因素之一。然而&#xff0c;并不是每个人都对这个职业有深刻的理解。因此&#xff0c;在本文中&#xff0c;我们…

【Git-驯化】一文学会git中对代码进行存储操作:git stash技巧

【Git-驯化】一文学会git中对代码进行存储操作&#xff1a;git stash技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内…

【无标题】DNS域名解析

回顾指令&#xff1a; samba机器&#xff1a; 安装samba Yum -y install samba 自建库&#xff0c;只下载不安装 Yum -y install --downloadonly --downloaddir./soft/ 配置samba Vim /etc/samba/smb.conf [smb_share] comment smb share service path /share/ guest…

python爬虫的基础知识

1.学习爬虫的好处 提升编程技能&#xff1a;爬虫开发需要掌握编程基础&#xff0c;特别是网络请求、HTML/CSS/JavaScript解析、数据存储和异常处理等技能。通过学习爬虫&#xff0c;你可以巩固和提升你的编程技能&#xff0c;特别是Python等编程语言的应用能力。 数据驱动决策…

力扣高频SQL 50题(基础版)第二十四题

文章目录 力扣高频SQL 50题&#xff08;基础版&#xff09;第二十四题1729.求关注者的数量题目说明实现过程准备数据实现方式结果截图 力扣高频SQL 50题&#xff08;基础版&#xff09;第二十四题 1729.求关注者的数量 题目说明 表&#xff1a; Followers ----------------…

QT--聊天室

一、设计要求 用QT做一个聊天室&#xff0c; 制作一个服务器和客户端。可以进行注册、登录&#xff0c; 登陆成功后可以使用昵称进行发送、接收消息。 能根据昵称、聊天内容查询历史记录&#xff0c;也可以查询全部聊天记录。 。 二、客户端三级ui界面 三、项目代码 //在…