Linux系统编程_网络编程:字节序、socket、serverclient、ftp 云盘
1. 网络编程概述(444.1)
TCP/UDP对比
- TCP 面向连接(如打电话要先拨号建立连接);UDP 是无连接的,即发送数据之前不需要建立连接
- TCP 提供可靠的服务。也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付
- TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流;UDP 是面向报文的 UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 IP 电话,实时视频会议等)
- 每一条 TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信
- TCP 首部开销 20 字节;UDP 的首部开销小,只有 8 个字节
- TCP 的逻辑通信信道是全双工的可靠信道,UDP 则是不可靠信道
端口号作用
- 一台拥有 IP 地址的主机可以提供许多服务,比如 Web 服务、FTP 服务、SMTP 服务等
- 这些服务完全可以通过 1 个 IP 地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠 IP 地址,因为 IP 地址与网络服务的关系是一对多的关系。
- 实际上是通过 “IP 地址 + 端口号” 来区分不同的服务的。端口提供了一种访问通道,服务器一般都是通过知名端口号来识别的。例如,对于每个 TCP/IP 实现来说,FTP 服务器的 TCP 端口号都是 21,每个 Telnet 服务器的 TCP 端口号都是 23,每个 TFTP (简单文件传送协议)服务器的 UDP 端口号都是 69。

2. 字节序(445.2)
- 字节序,即字节在电脑中存放时的序列与输入(输出)时的序列是先到的在前还是后到的在前。
- 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。
- Little endian:将低序字节存储在起始地址
- Big endian:将高序字节存储在起始地址
- LE little-endian 小端字节序
- BE big-endian 大端字节序
- 网络字节序 = 大端字节序

字节序转换api
#include <arpa/inet.h>uint16_t htons(uint16_t host16bitvalue); //返回网络字节序的值
uint32_t htonl(uint32_t host32bitvalue); //返回网络字节序的值
uint16_t ntohs(uint16_t net16bitvalue); //返回主机字节序的值
uint32_t ntohl(uint32_t net32bitvalue); //返回主机字节序的值
- h代表host主机,n代表net,s代表short(两个字节),l代表long(4个字节),通过上面的4个函数可以实现主机字节序和网络字节序之间的转换。有时可以用INADDR_ANY,INADDR_ANY指定地址让操作系统自己获取
3. socket编程步骤(446.3)

Sockt服务器和客户端的开发步骤

- TCP Server
- 创建套接字(socket)
- 为套接字添加信息(IP地址和端口号)(bind)
- 监听网络连接(listen)
- 监听到有客户端接入,接受一个连接(accept)
- 数据交互(read、write、read)
- 关闭套接字,断开连接(close)
4. Linux提供的API简析(447.4)
- 指定讲“汉语”(连接协议)

int socket(int domain, int type, int protocol);

- 地址准备好


- 地址转换API
int inet_aton(const char* straddr,struct in_addr *addrp);
把字符串形式的“192.168.1.123”转为网络能识别的格式char* inet_ntoa(struct in_addr inaddr);
把网络格式的ip地址转为字符串形式
-
监听


-
连接

-
数据收发
5.1 数据收发常用第一套API

5.2 数据收发常用第二套API

- 客户端的connect函数

5. socket服务端代码实现一(448.5)
man 2 socket、man 2 bind、man htons、man inet_aton
查找某段源码在哪个头文件之下的方法
cd /usr/includelsgrep "struct sockaddr_in {" * -nir- 搜索其在哪个头文件下被定义/声明
- ※ (星号) 在当前目录底下
- n 找出时显示其所在行号
- i 不区分大小写
- r 递归的方式
vi linux/in.h +261


grep "struct in_addr {" * -nirvi linux/in.h +89


代码相关
- SOCKET/server.c
#include <stdio.h>//printf
#include <sys/types.h>//socket bind /* See NOTES */
#include <sys/socket.h>//socket bind
//#include <linux/in.h>//struct sockaddr_in//和<netinet/in.h>冲突
#include <arpa/inet.h>//htons
#include <netinet/in.h>//inet_aton
#include <stdlib.h>//exit
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct sockaddr_in {//也可在<linux/in.h>中找到__kernel_sa_family_t sin_family; /* Address family */
//__be16 sin_port; /* Port number */
//struct in_addr sin_addr; /* Internet address *//* Pad to size of `struct sockaddr'. */
//unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
// sizeof(unsigned short int) - sizeof(struct in_addr)];
//};*/
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址,客户端地址长度地址,返回新的建立的socket的通道
int main(int argc, char **argv)
{int s_fd;//1. socket 获取/创建套接字s_fd = socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域,TCP协议,自动选择type类型对应的默认协议(也可用宏:IPPROTO_TCP TCP)if(s_fd == -1){//判断建立socket通道是否成功perror("socket");//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定struct sockaddr_in s_addr;s_addr.sin_family = AF_INET;//协议族,跟domain一致s_addr.sin_port = htons(8989);//端口号一般3000以下为操作系统来用,建议用户5000以上 端口号由主机to网络 返回网络字节序的值inet_aton("192.168.2.13",&s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//fd,强转为struct sockaddr型,结构体的长度//3. listenlisten(s_fd,10);//监听10个连接,不阻塞//4. accept 接受int c_fd = accept(s_fd,NULL,NULL);//先不关心客户端是谁//如果没连接到,会卡在这//后续的操作用新的c_fd//5. read//6. writeprintf("connected!\n");while(1)//有客户端连上,不让其退出return 0;
}


ifconfig本机网络地址和本机回环地址:

win10 telnet不是内部或外部命令(已解决)
- telnet 在win10下默认是不开启的,所以需要我们自己手动开启。
- win+s 搜索:控制面板,点击进入;

- 在控制面板中,选择程序——启动或关闭 windows 功能,勾选 Telnet 客户端选项,确定进行安装。

勾选 “Telnet 客户端”

更改 windows 设置需要一分钟左右的时间,不要关闭。安装完成后重启计算机生效。(实测可不重启)

- windows功能的telnet功能已经开启,我们测试下是否可以正常使用,输入telnet+ip地址。

6. socket服务端代码实现二(449.6)
- SOCKET/server2.c(建立服务器并等待客户端连接 后收发)
#include <stdio.h>//printf
#include <sys/types.h>//socket bind /* See NOTES */
#include <sys/socket.h>//socket bind
//#include <linux/in.h>//struct sockaddr_in//和<netinet/in.h>冲突
#include <arpa/inet.h>//htons
#include <netinet/in.h>//inet_aton
#include <stdlib.h>//exit
#include <string.h>//memset
#include <unistd.h>//read write
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址,客户端地址长度,返回新的建立的socket的通道
int main()
{int s_fd;//1. socketint c_fd;//4. acceptint n_read;//5. readchar readBuf[128];//5. read//定义一个数组就不用像指针还要开辟空间char *msg = "I get your connection\n";//6. writestruct sockaddr_in s_addr;//2. bindstruct sockaddr_in c_addr;//2. bindmemset(&s_addr,0,sizeof(struct sockaddr_in));//清空memset(&c_addr,0,sizeof(struct sockaddr_in));//清空//1. socket 获取/创建套接字s_fd = socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域,TCP协议,自动选择type类型对应的默认协议(也可用宏:IPPROTO_TCP TCP)if(s_fd == -1){//判断建立socket通道是否成功perror("socket");//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定s_addr.sin_family = AF_INET;//协议族,跟domain一致s_addr.sin_port = htons(8989);//端口号一般3000以下为操作系统来用,建议用户5000以上 端口号由主机to网络 返回网络字节序的值inet_aton("192.168.2.13",&s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//3. listenlisten(s_fd,10);//监听10个连接//4. accept 接受int clen = sizeof(struct sockaddr_in);c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);//如果没连接到,会卡在这if(c_fd == -1){perror("accept");}printf("get connected: %s\n",inet_ntoa(c_addr.sin_addr));//连上后打印 “已连接” 和客户端的 ip地址//5. readn_read = read(c_fd, readBuf, 128);if(n_read == -1){perror("read");}else{printf("get message:%d,%s\n",n_read,readBuf);//打印收到了多少个字节的消息,和消息的内容}//6. writewrite(c_fd,msg,strlen(msg));//用提前定义的字符串,如直接写入字符串,字节大小也随意写如128,会造成乱码因有无用的字节return 0;
}

7. socket客户端代码实现(450.7)
man 2 connect- SOCKET/client.c(连接服务器后 客户端发收)
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>//read write
//int socket(int domain, int type, int protocol);
//int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int main(int argc, char **argv)
{int c_fd;//1. socketint n_read;//4. readchar readBuf[128];//4. readchar *msg = "I'm a msg from Client";//3. write//1. socket 获取/创建套接字c_fd = socket(AF_INET, SOCK_STREAM, 0);if(c_fd == -1){perror("socket");exit(-1);}//2.connect//连接服务器 struct sockaddr_in c_addr;memset(&c_addr,0,sizeof(struct sockaddr_in));c_addr.sin_family = AF_INET;c_addr.sin_port = htons(8989);inet_aton("192.168.2.13",&c_addr.sin_addr);//服务器的ip地址if(connect(c_fd, (struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){//连接时会阻塞,直到出结果为之perror("connect");exit(-1);}//3. write//写write(c_fd,msg,strlen(msg));//4. read//读 n_read = read(c_fd, readBuf, 128);if(n_read == -1){perror("read");}else{printf("get message from server:%d,%s\n",n_read,readBuf);//打印收到了多少个字节的消息,和消息的内容}return 0;
}

8. 实现双方聊天(451.8)

- SOCKET/server3.c(服务器可以一直接收多个客户端的连接,并和某个客户端互发消息)
#include <stdio.h>//printf
#include <sys/types.h>//socket bind /* See NOTES */
#include <sys/socket.h>//socket bind
//#include <linux/in.h>//struct sockaddr_in//冲突
#include <arpa/inet.h>//htons
#include <netinet/in.h>//inet_aton
#include <stdlib.h>//exit
#include <string.h>//memset
#include <unistd.h>//read write
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址,客户端地址长度,返回新的建立的socket的通道
int main(int argc, char **argv)
{int s_fd;//1. socketint c_fd;//4. acceptint n_read;//5. readchar readBuf[128];//5. read// char *msg = "I get your connection";char msg[128] = {0};//6. writestruct sockaddr_in s_addr;//2. bindstruct sockaddr_in c_addr;//2. bindmemset(&s_addr,0,sizeof(struct sockaddr_in));memset(&c_addr,0,sizeof(struct sockaddr_in));if(argc != 3){//如果没有输入参数 会提示printf("param is not good\n");exit(-1);}//1. socket 获取套接字s_fd = socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域,TCP协议,自动选择type类型对应的默认协议(也可用宏:IPPROTO_TCP TCP)if(s_fd == -1){//判断建立socket通道是否成功perror("socket");//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定s_addr.sin_family = AF_INET;//协议族,跟domain一致s_addr.sin_port = htons(atoi(argv[2]));//字符串转换为整形数inet_aton(argv[1],&s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//3. listenlisten(s_fd,10);//监听10个连接//4. accept 接受连接int clen = sizeof(struct sockaddr_in);while(1){//不让程序退出 一直循环进行//不要在while(1)里定义变量//同时收和发c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);//如果没连接到,会卡在这if(c_fd == -1){perror("accept");}printf("get connected: %s\n",inet_ntoa(c_addr.sin_addr));//连上后打印 “已连接” 和客户端的 ip地址if(fork() == 0){//在网络服务进程中父进程等待客户端的服务请求 当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达//6. writeif(fork()==0){//如果要用两个while(1),要么用多线程,要么用fork创建子进程while(1){memset(msg,0,sizeof(msg));printf("input: ");//gets(msg);//gets不安全,已经被废弃fgets(msg,sizeof(msg),stdin);//阻塞msg[strcspn(msg, "\n")] = '\0';//移除输入中的换行符write(c_fd,msg,strlen(msg));//6. write} } //5. readwhile(1){memset(readBuf,0,sizeof(readBuf));//每次写之前清空n_read = read(c_fd, readBuf, 128);//阻塞if(n_read == -1){perror("read");}else{printf("get message from client:%d,%s\n",n_read,readBuf);//打印收到了多少个字节的消息,和消息的内容}}}}return 0;
}
- SOCKET/client2.c(多个客户端分别连接服务器,并和服务器互发消息)
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>//read write
//int socket(int domain, int type, int protocol);
//int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//char *fgets(char *s, int size, FILE *stream);
int main(int argc, char **argv)
{int c_fd;//1. socketint n_read;//4. readchar readBuf[128];//4. read//char *msg = "I'm a msg from Client";//3. write char msg[128] = {0};if(argc != 3){//如果没有输入参数 会提示printf("param is not good\n");exit(-1);}//1. socket 获取/创建套接字c_fd = socket(AF_INET, SOCK_STREAM, 0);if(c_fd == -1){perror("socket");exit(-1);}//2.connect 连接服务器 struct sockaddr_in c_addr;memset(&c_addr,0,sizeof(struct sockaddr_in));c_addr.sin_family = AF_INET;c_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1],&c_addr.sin_addr);//服务器的ip地址if(connect(c_fd, (struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){//连接时阻塞 成功后往下perror("connect");exit(-1);}while(1){//不让程序退出 一直循环进行//同时发和收//3. write 写if(fork()==0){//如果要用两个while(1),要么用多线程,要么用fork创建子进程while(1){memset(msg,0,sizeof(msg));//每次写之前清空printf("input: ");//gets(msg);//gets不安全,已经被废弃fgets(msg,sizeof(msg),stdin);//阻塞msg[strcspn(msg, "\n")] = '\0';//移除输入中的换行符write(c_fd,msg,strlen(msg));}}//4. read 读while(1){memset(readBuf,0,sizeof(readBuf));n_read = read(c_fd, readBuf, 128);//阻塞if(n_read == -1){perror("read");}else{printf("get message from server:%d,%s\n",n_read,readBuf);//打印收到了多少个字节的消息,和消息的内容}}}return 0;
}

9. 多方消息收发(452.9)
- 上节课的逻辑:shell终端获得输入,并不知道是哪个子进程的输入,所以返回给客户端也并不知道是哪个(子进程之间存在资源竞争)

- SOCKET/server4.c(自动主动回复给客户端消息,类似心跳包)
#include <stdio.h>//printf
#include <sys/types.h>//socket bind /* See NOTES */
#include <sys/socket.h>//socket bind
//#include <linux/in.h>//struct sockaddr_in//冲突
#include <arpa/inet.h>//htons
#include <netinet/in.h>//inet_aton
#include <stdlib.h>//exit
#include <string.h>//memset
#include <unistd.h>//read write
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址,客户端地址长度,返回新的建立的socket的通道
int main(int argc, char **argv)
{int s_fd;//1. socketint c_fd;//4. acceptint n_read;//5. readint mark = 0;//第几个客户端char readBuf[128];//5. read// char *msg = "I get your connection";char msg[128] = {0};//6. writestruct sockaddr_in s_addr;//2. bindstruct sockaddr_in c_addr;//2. bindmemset(&s_addr,0,sizeof(struct sockaddr_in));memset(&c_addr,0,sizeof(struct sockaddr_in));if(argc != 3){//如果没有输入参数 会提示printf("param is not good\n");exit(-1);}//1. socket 获取套接字s_fd = socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域,TCP协议,自动选择type类型对应的默认协议(也可用宏:IPPROTO_TCP TCP)if(s_fd == -1){//判断建立socket通道是否成功perror("socket");//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定s_addr.sin_family = AF_INET;//协议族,跟domain一致s_addr.sin_port = htons(atoi(argv[2]));//字符串转换为整形数inet_aton(argv[1],&s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//3. listenlisten(s_fd,10);//监听10个连接//4. accept 接受连接int clen = sizeof(struct sockaddr_in);while(1){//不让程序退出 一直循环进行//不要在while(1)里定义变量//同时收和发c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);//如果没连接到,会卡在这if(c_fd == -1){perror("accept");}mark++;printf("get connected: %s\n",inet_ntoa(c_addr.sin_addr));//连上后打印 “已连接” 和客户端的 ip地址if(fork() == 0){//在网络服务进程中父进程等待客户端的服务请求 当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达//一有客户端接入就调用子进程//6. writeif(fork()==0){//如果要用两个while(1),要么用多线程,要么用fork创建子进程while(1){sprintf(msg,"welcome NO.%d Client",mark);//每个客户端都能知道其连接有无丢失write(c_fd,msg,strlen(msg));//6. write//对于服务端都能收到客户端的请求sleep(3);//类似心跳包,每隔3s发一串话} } //5. readwhile(1){//接收每一个客户端发来的消息memset(readBuf,0,sizeof(readBuf));//每次写之前清空n_read = read(c_fd, readBuf, 128);//阻塞if(n_read == -1){perror("read");}else{printf("get message from NO.%d Client :%d,%s\n",mark,n_read,readBuf);//打印收到了多少个字节的消息,和消息的内容}}}}return 0;
}

10. 项目运行结果(453.1)

11. 项目研发思路(454.2)
客户端要实现的指令:
- get a.c:获取服务器的文件 a.c
- put a.c:上传文件 a.c 到服务器
- cd a:进入服务器某文件夹 a
- ls:展示服务器有哪些文件和文件夹
- pwd:显示当前文件夹所在路径
- lcd aa:进入客户端本地的某文件夹 aa
- lls:展示客户端本地有哪些文件和文件夹
- quit:退出连接
服务端去解析这些指令,执行这些指令,返回这些指令的结果
- 自行搜索 “Linux 判断文件是否存在” 的函数,写 demo 测试,再整合进项目中

- recv 和 read 区别:
- recv 第四个参数 MSG_PEEK 就可以多次读,其返回值等0时表示客户端连接断开,小于0读数据失败
- read 只能读一次套接字中的数据就


12. 项目指导(455.3)
- 服务端




- 客户端






相关文章:
Linux系统编程_网络编程:字节序、socket、serverclient、ftp 云盘
1. 网络编程概述(444.1) TCP/UDP对比 TCP 面向连接(如打电话要先拨号建立连接);UDP 是无连接的,即发送数据之前不需要建立连接TCP 提供可靠的服务。也就是说,通过 TCP 连接传送的数据…...
队列(8.6)
目录 2.队列 2.1队列的概念及结构 2.2队列的实现 2.2.1初始化队列 2.2.2队尾入队列 2.2.3队头出队列 2.2.4获取队列头部元素 2.2.5 销毁队列 3.栈和队列面试题 225. 用队列实现栈 - 力扣(LeetCode) 232. 用栈实现队列 - 力扣(LeetC…...
计算机网络 第四章网络层
文章目录 1 网络层的功能2 数据交换方式:电路交换3 数据交换方式:报文交换4 数据交换方式:分组交换5 数据交换方式:数据报方式6 数据交换方式:虚电路方式及各种方式对比7 路由算法及路由协议8 IP数据报的概念和格式9 I…...
操作系统运行机制
文章目录 操作系统运行机制特权指令VS非特权指令内核态VS用户态中断和异常内中断(异常)外中断中断机制基本原理中断处理过程 系统调用系统调用和库函数的区别为什系统调用时必须的?什么功能需要用到系统调用系统调用的过程小结 操作系统内核 操作系统运行机制 特权…...
mathtype7.4破解永久激活码
MathType(数学公式编辑器)是由Design Science公司研发的一款专业的数学公式编辑工具。MathType功能非常强大,尤其适用于专门研究数学领域的人群使用。使用MathType让你在输入数学公式的时候能够更加的得心应手,各种复杂的运算符号也不在话下。 MathType最…...
66 内网安全-域横向批量atschtasksimpacket
目录 演示案例:横向渗透明文传递at&schtasks 案例2-横向渗透明文HASH传递atexec-impacket案例3-横向渗透明文HASH传递批量利用-综合案例5-探针主机域控架构服务操作演示 传递攻击是建立在明文和hash值的一个获取基础上的攻击,也是在内网里面常见协议的攻击&…...
PCI9054入门1:硬件引脚定义、时序、FPGA端驱动源码
文章目录 1:PCI9054的FPGA侧(local侧引脚定义)2:PCI9054的C模式下的读写时序3:FPGA代码部分具体代码: 1:PCI9054的FPGA侧(local侧引脚定义) 而PCI9054的本地总线端的主要…...
多媒体应用设计师 第17章 多媒体应用场景的技术应用和实现示例
口诀 思维导图 2020...
react151618刷新几次的问题
结论: 16 hooks版本 默认render1次 同步中,无论多少种类还是次数,都render 1次。 异步中,无论多少种类还是次数,1个种类执行1次,多次的话,用n*2。 18 hooks版本 默认render2次, 同步…...
【Spring】IOC容器与Bean的常用属性配置
文章目录 1.前言2.IOC容器2.1 BeanFactory 容器2.2 ApplicationContext 容器 3.Bean的常用属性配置4. 总结 1.前言 在之前的文章-IOC的快速入门中讲过Bean这个概念. 本来就来介绍容器与Bean的常用属性配置 在Spring框架中,Bean指的是被Spring加载生成出来的对象。 …...
2023年下半年 系统集成项目管理工程师 真题考点(一二三四批次)(10月28、29)(网友回忆版)
文章目录 第一批部分考点整体管理采购管理风险管理二:EAC 第二批部分考点如下: 第三批部分考点如下: 第一批 部分考点 1、案例考了关键路径和工期,风险管理、采购、风险、招投标,整体管理。 2、计算题有关键路径和挣…...
读韩都衣舍,谈权力转移的激励制度
这是一个很久之前的商业案例。 在大公司,管理过于复杂,成了现在公司管理的大问题。大公司的流程长,市场的突击速度慢,以及员工的积极性差,成为大公司的一个潜在的弊病。而最近,从韩都衣舍的创始人赵迎光的…...
私有云:【10】VCenter安装win10
私有云:【10】VCenter安装win10 1、ESXI挂载win10镜像2、VCenter安装win102.1、创建虚拟机2.2、启动虚拟机 此WIN10用来作为以后的远程桌面 1、ESXI挂载win10镜像 2、VCenter安装win10 2.1、创建虚拟机 创建虚拟机 设置名称下一步 选择计算机资源 选择NFS存储 设置…...
[Java/力扣100]判断两棵二叉树是否相同
我希望通过这道题,能进一步了解递归思想和“树是递归定义的”这句话 分析 我们的目的是写一个方法来检验两棵树是否相同 什么叫“两棵树相同”?——相同的位置存在相同的结点 有三种情况:1、两棵树一颗为空一颗不为空——不相同ÿ…...
BEC商务英语主题 定价策略|柯桥学商务英语口语
Factors in Pricing Decisions 影响价格制定的因素 A firm cannot determine a product’s price without considering several factors that affect price. 在制定产品价格时,公司如果不考虑影响价格的各种因素是无法制定的。 Managers must take into account t…...
第七章 ObjectScript 一般系统限制
文章目录 第七章 ObjectScript 一般系统限制 字符串长度限制下标限制Global的最大长度 第七章 ObjectScript 一般系统限制 字符串长度限制 字符串的长度有限制:3,641,144 个字符。 重要的是要认识到字符串不仅仅是从输入/输出设备读取的结果。它们可以显示在其他上…...
【Python百练——第1练】使用Python求100以内的所有偶数
作者:Insist-- 个人主页:insist--个人主页 作者简介:梦想从未散场,传奇永不落幕,持续更新优质网络知识、Python知识、Linux知识以及各种小技巧,愿你我共同在CSDN进步 欢迎点赞👍收藏Ὄ…...
springboot心理咨询管理系统
springboot心理咨询管理系统,java心理咨询管理系统,心理咨询管理系统 运行环境: JAVA版本:JDK1.8 IDE类型:IDEA、Eclipse都可运行 数据库类型:MySql(8.x版本都可) 硬件环境…...
Java-API简析_java.net.URL类(基于 Latest JDK)(浅析源码)
【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/134024288 出自【进步*于辰的博客】 因为我发现目前,我对Java-API的学习意识比较薄弱…...
C语言浮点型在内存中的存储
目录 前言: 引言: 浮点数存储规则 举个栗子: TIP: 单精度浮点数存储的模型(float) 双精度浮点数存储的模型(double) IEEE对 M 的特殊规定 IEEE对 E 的特殊规定 小试牛刀 先…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
