Linux系统编程项目——FTP云盘

2023-11-14

一、项目实现功能

  • 在客户端对服务端的操作:
    1.获取服务器的文件(get)
    2.查看服务器当前路径下的所有文件(ls)
    3.进入服务器的某个路径(cd)
    4.上传文件到服务器(put)
    5.查看服务器当前在那个文件夹(pwd)
    6.退出 (quit)

  • 在客户端本地的功能实现:
    1.查看客户端本地当前路径有哪些文件(lls)
    2.进入客户端的某个路径(lcd)
    3.查看客户端当前在那个文件夹下(lpwd)
    4.退出连接(quit)

二、项目实现思路

  • 服务器:

1.创建套接字(socket)
2.将socket与IP地址和端口绑定(bind)
3.监听被绑定的端口(listen)
4.接收连接请求(accept)
5.当有客户端接入时创建子进程对接并处理客户端发来的请求

  • 客户端:

1.创建套接字(socket)
2.连接指定计算机的端口(connect)
3.接收输入向socket中写入信息(write)
4.获取客户端发送的内容像ls,pwd,get指令,需要进行(read)

  • 指令的实现思路

lspwd:调用popen函数,执行命令,并获取执行命令后的输出内容,将内容发回到客户端

cd:将cd指令发送到服务器,在服务器端调用chdir实现路径的切换

get:客户端获取服务器的某个文件,服务器首先通过access函数判断文件是否存在,存在则将文件的内容发送到客户端,客户端创建文件,并将服务器发送的内容保存至文件中,实现get指令。

put:客户端向服务器发送文件,客户端首先通过access函数判断文件是否存在,存在则将文件的内容发送到服务器,服务器创建文件,并将客户端发送的内容保存至文件中,实现put指令。

llslpwd:调用system函数即可。

lcd:在客户端直接调用chdir函数即可

三、项目用到的函数

1.access函数(判断文件是否存在的函数)

  • 函数原型:
 int access(const char *pathname, int mode);
  • 函数说明:
    判断参数中的文件民是否存在
  • 参数:
    pathname:需要检测的文件路径名
    mode:需要测试的操作模式
    R_OK 测试读许可权
    W_OK 测试写许可权
    X_OK 测试执行许可权
    F_OK 测试文件是否存在
  • 返回值:成功执行时,返回0,失败返回-1,errno被设为以下的某个值

2.chdir函数(进入某个文件夹的函数)

  • 函数原型:
int chdir(const char *path);
  • 函数说明:切换到参数所设置的路径
  • 参数:所指代的工作目录(即将要进入的工作目录)
  • 返回值:成功返回0,失败返回-1,errno为错误代码

3.fgets函数(可以获取空格,且较为安全)

  • 函数原型:
char *fgets(char *s, int size, FILE *stream);
  • 函数说明:
    虽然用 gets() 时有空格也可以直接输入,但是 gets() 有一个非常大的缺陷,即它不检查预留存储区是否能够容纳实际输入的数据,换句话说,如果输入的字符数目大于数组的长度,gets 无法检测到这个问题,就会发生内存越界,所以编程时建议使用 fgets()。但是调用次函数会把回车\n也作为字符串的一部分,因此需要将去掉换行符删掉:
if(msg.cmd[strlen(msg.cmd) - 1] == '\n'){  			
	msg.cmd[strlen(msg.cmd) - 1] = '\0'; 
 }
  • 参数:
    s:代表要保存到的内存空间的首地址,可以是字符数组名,也可以是指向字符数组的字符指针变量名
    size:代表的是读取字符串的长度
    stream:表示从何种流中读取,可以是标准输入流 stdin,也可以是文件流,即从某个文件中读取
  • 返回值:返回该数组的指针(首地址),如果读完,则返回空指针NULL

四、代码

  • 服务端
#include <stdio.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include <sys/stat.h>
#include <fcntl.h>

char *get_cmd_dir(char *cmd)
{
	char *p=NULL;
	p=strtok(cmd," ");
	p=strtok(NULL," ");
	return p;
}//用此函数将用户输入的指令中的文件名分割开来 如cd xx,将得到xx


int get_cmd_type(char *cmd)
{
	if(!strcmp("ls",cmd)) return LS;
	if(!strcmp("pwd",cmd)) return PWD;
	if(!strcmp("quit",cmd)) return QUIT;

	
	if(strstr(cmd,"get")!=NULL) return GET;
	if(strstr(cmd,"cd")!=NULL) return CD;
	if(strstr(cmd,"put")!=NULL) return PUT;
	

	return -1;

}//用此函数将用户输入的指令对应与之相应的宏,便于之后对指令进行判断处理
void message_handler(struct Msg msg,int fd)//指令处理函数
{
	int ret;
	char *dir;
	char *fileName;
	int fdFile;
	int getSize;
	char *dataBuf;
	
	printf("get cmd: %s\n",msg.cmd);//打印客户端传来的指令

	ret =get_cmd_type(msg.cmd);

	switch (ret){
		case LS:
		case PWD:
			msg.type=0;
			//用popen()函数,获取运行的结果,可以存放在字符串当
			FILE *fp=popen(msg.cmd,"r");
			fread(msg.data,sizeof(msg.data),1,fp);//用popen函数打开的文件可以用fread函数读到相应的地方
			write(fd,&msg,sizeof(msg));//将数据发回到客户端
			pclose(fp);
			break;
		case CD:
			msg.type=1;
			dir=get_cmd_dir(msg.cmd);//首先需要获取cd 后的文件名字,这里勇封装函数获取文件名字	
			chdir(dir);//调用chdir指令,相当于cd
			break;
		case GET:
			fileName=get_cmd_dir(msg.cmd);//获取需要拷贝的文件名
			if(access(fileName,F_OK)==-1){//用access 函数判断文件是否存在,若不存在返回-1
				strcpy(msg.data,"This File is not exist");
				write(fd,&msg,sizeof(msg));//将不存在的提升发回客户端
			}else{
				msg.type=DOFILE;//若存在,则执行对文件的拷贝
				fdFile=open(fileName,O_RDWR);//存在打开文件
				getSize = lseek(fdFile,0,SEEK_END);
				lseek(fdFile,0,SEEK_SET);
				read(fdFile,msg.secondBuf,getSize);//把文件内容写入secondBuf中
				close(fdFile);
				write(fd,&msg,sizeof(msg));//将文件内容存放在结构体中并发给客户端
				
			}			
			break;
		case PUT://客户端上传文件到服务器,客户端函数与服务器的GET函数类似,将要上传的文件内容拷贝到结构体中
			fdFile=open(get_cmd_dir(msg.cmd),O_RDWR|O_CREAT,0666);//服务器首先创建并打开要上出的文件
			write(fdFile,msg.secondBuf,sizeof(msg.secondBuf));//然后将客户端上传给服务器文件里的内容拷贝到新创建的文件中
			close(fdFile);
			break;
		case QUIT://客户端发送quit指令,服务器得到指令后打印客户端退出
			printf("client quit\n");
			exit(-1);
		
		
	}
}

int main(int argc,char * argv[])
{
	int socket_fd;
	int connect_fd;
	int nread;
	int clen;//struct sockaddr_in 结构体长度
	char readBuf[128];
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;
	struct Msg message;

	if(argc != 2){
		printf("输入端口号");
		exit(-1);
	}
	
	memset(&s_addr,0,sizeof(struct sockaddr));
	memset(&c_addr,0,sizeof(struct sockaddr));
	memset(&message,0,sizeof(struct Msg));

	socket_fd=socket(AF_INET,SOCK_STREAM,0);//创建套接字
	if(socket_fd==-1){
		perror("socket");
		exit(-1);
	}

	s_addr.sin_family=AF_INET;
	s_addr.sin_port=htons(atoi(argv[1]));

	inet_aton(" 127.0.0.1",&(s_addr.sin_addr));
	bind(socket_fd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in));//为套接字添加信息


	listen(socket_fd,10);//监听,等待客户端连接

	clen=sizeof(struct sockaddr_in);
	while(1){
		connect_fd=accept(socket_fd,(struct sockaddr*)&c_addr,&clen);//不断的检测是否有客户端接入,若有就创建一个子进程对接接入的客户端
		if(connect_fd==-1){

			perror("accept");
		}

		printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));

			if(fork()==0){//创建子进程进行对客户端的对接
				while(1){
					memset(&message,0,sizeof(message));//首先将用来传输数据的结构体里的内容置0
					nread=read(connect_fd,&message,sizeof(message));//读取客户端向服务器传送的数据结构体
					if(nread==0){
						printf("client out\n");
						break;
					}else if(nread>0){
						message_handler(message,connect_fd);//将读取出来的数据送入此函数处理						
					}
				}
			}
	
	}		
	close (connect_fd);
	close(socket_fd);
	return 0;
}


  • 客户端
#include <stdio.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include <sys/stat.h>
#include <fcntl.h>


char *get_cmd_dir(char *cmd)
{
	char *p=NULL;
	p=strtok(cmd," ");
	p=strtok(NULL," ");
	return p;
}//用此函数将用户输入的指令中的文件名分割开来 如cd xx,将得到xx

int get_cmd_type(char *cmd)
{
	if(strcmp("lls",cmd)==0)	return LLS;
	if(strstr(cmd,"lcd")!=NULL) return LCD;//注意,lcd包含cd需要在cd之前
	if(strcmp("ls",cmd)==0)		return LS;
	if(strcmp("pwd",cmd)==0)	return PWD;
	if(strcmp("quit",cmd)==0)	return QUIT;
	if(strstr(cmd,"cd")!=NULL)	return CD;
	if(strstr(cmd,"get")!=NULL) return GET;
	if(strstr(cmd,"put")!=NULL) return PUT;
	if(!strcmp(cmd,"lpwd"))     return LPWD;

	return -1;
	
}//用此函数得到客户端输入指令的宏,指令处理函数的判断

int cmd_handler(struct Msg msg,int fd)
{
	int ret;
	char *dir;
	char cmdTemp[128];
	int fdFile;
	int putSize;
	ret=get_cmd_type(msg.cmd);
		
	switch (ret)
		{
		case LS:
		case PWD:
		case CD:
		case GET:
			write(fd,&msg,sizeof(msg));			
			
			break;//当输入的指令需要在服务器上完成时,将指令直接发送给服务器

		case PUT://与服务器对于GET指令处理的方法类似
			strcpy(cmdTemp,msg.cmd);//防止strok破坏msg.cmd
			dir=get_cmd_dir(cmdTemp);
			printf("cmd :%s\n",msg.cmd);
			if(access(dir,F_OK)==-1){//用access 函数判断文件是否存在
				printf("%s this file no exit\n",dir);
				
			}else{
				fdFile=open(dir,O_RDWR);//存在打开文件
				putSize = lseek(fdFile,0,SEEK_END);//获取文件的字节数
				lseek(fdFile,0,SEEK_SET);
				read(fdFile,msg.secondBuf,putSize);
				close(fdFile);
				write(fd,&msg,sizeof(msg));
				
			}	
			
			break;
		case LCD://客户端的cd指令
			dir=get_cmd_dir(msg.cmd);
			printf("the dir:%s\n",dir);
			chdir(dir);
			break;
		case LLS://客户端的lls指令
			system("ls");
			break;
		case QUIT:
			strcpy(msg.cmd,"quit");
			write(fd,&msg,sizeof(msg));	
			close(fd);
			exit(-1);										
		case LPWD:
			system("pwd");
			break;
		}
	return ret;
	

}
void c_msg_handler(struct Msg msg,int fd)//信息处理函数,显示结果
{
		int n_read;
		int filefd;
		struct Msg getmsg;//服务器发送到客户端的结构体消息
		char *filename;
		
		//getmsg.secondBuf = (char *)malloc(1024);
		//memset(getmsg.secondBuf,'\0',1024);
		n_read =read(fd,&getmsg,sizeof(getmsg));//读取服务器向客户端发送数据
		if(n_read == 0){
			printf("sever is quit\n");
			exit(-1);
		}
		if(getmsg.type == DOFILE){//当客户端输入的指令是GET时,需要在客户端创建需要获取的文件
			filename=get_cmd_dir(msg.cmd);//msg.cmd 客户端要发送给服务器的消息结构体
			filefd=open(filename,O_RDWR|O_CREAT,0666);
			write(filefd,getmsg.secondBuf,strlen(getmsg.secondBuf));
			close(filefd);
			fflush(stdout); //调用printf()时,输出的结果一般会被标准库缓存起来,可能不会及时打印写出到输出设备上面,此时就可以用fflush(stdout)强制把缓存内容进行输出
		}
		else{//将需要在服务器执行的指令的运行结果打印
			printf("---------------------\n");
			printf("%s\n",getmsg.data);
			printf("---------------------\n");
		}


}
int main(int argc,char *argv[])
{
	int client_fd;
	int nread;	
	int ret;
	char readBuf[128];
	
	struct sockaddr_in client_addr;
	struct Msg msg;

	if(argc !=3){
		printf("请输入IP地址和端口号\n");
		exit(-1);
	}
	memset(&client_addr,0,sizeof(struct sockaddr));

	client_fd=socket(AF_INET,SOCK_STREAM,0);
	if(client_fd==-1){
		perror("socket");
		exit(-1);
	}

	client_addr.sin_family=AF_INET;
	client_addr.sin_port=htons(atoi(argv[2]));

	inet_aton(argv[1],&(client_addr.sin_addr));


	if(connect(client_fd,(struct sockaddr*)&client_addr,sizeof(struct sockaddr))==-1){

		perror("connect");
		exit(-1);
	}
	printf("connecting.....\n");//连接客户端
	while(1){
		memset(&msg,0,sizeof(msg));
		putchar('>');
		fgets(msg.cmd,1024,stdin);
		if(msg.cmd[strlen(msg.cmd) - 1] == '\n')  {      // 去掉换行符
    		 msg.cmd[strlen(msg.cmd) - 1] = '\0'; }
		//gets(msg.cmd);
		ret=cmd_handler(msg,client_fd);//将获取的指令送入指令处理函数中,并将返回的值判断
		if(ret>IFGO){//如果输入的指令像ls,pwd等需要在服务器完成处理的则进行下面的操作,而像lls这样在客户端
			continue;//完成的指令不需要向服务器进行数据交流,完成后直接退出循环进行下一次指令的输入
		}
		if(ret==-1){
			printf("cmd error,please put new cmd\n");
			continue;
		}
		c_msg_handler(msg,client_fd);

	}

	return 0;
}
  • config.h
#define LS 0
#define GET 1
#define PWD 2

#define IFGO 3


#define LCD 4
#define LLS 5
#define CD 6
#define PUT 7
#define QUIT 8
#define DOFILE 9
#define LPWD 10


struct Msg
{	
	int type;
	char cmd[1024];
	char data[1024];
	char secondBuf[1024];
};

五、项目总结(遇到的问题)

1.在客户端进行put操作时,为防止strtok将字符串破坏,导致无法获取put的目标文件,需要在引入一个字符串的变量保存。

strcpy(cmdTemp,msg.cmd);//防止strok破坏msg.cmd
dir=get_cmd_dir(cmdTemp);

2.在进行对输入字符串进行检测的时候,lcd的检测一定要放在cd的前面,因为cdlcd中的一个子字符串,所以如果cd的检测是放在lcd的前面的话,那么无论是输入的是cd还是lcd,都会是返回cd

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux系统编程项目——FTP云盘 的相关文章

  • 如何将域名附加到我的服务器? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我有一个小问题 查看了这里和其他论坛 但找不到解决方案 我的网站位于 my domain com 网站位于共享主机上 在我的域名注册中 我添加了当我为
  • 如何在bash中使用kill SIGUSR2?

    我在linux中使用iptraf来监控网络流量 shell命令是 让iptraf在后台运行 iptraf s eth0 f B L traffic dat 如果我想得到结果 我必须先停止 iptraf 所以我使用 shell 命令 kill
  • 如何在 Ubuntu x64 中使用 ptrace 插入 int3?

    我正在努力追随本指南 http eli thegreenplace net 2011 01 27 how debuggers work part 2 breakpoints 通过设置断点达到相同的结果 唯一的区别是我在 x64 系统上 所以
  • 拼写检查 shell 脚本

    我有一些疑问 我对一个应该是简单拼写检查器的脚本有疑问 它的目的是 当发现错误的单词时 它会提示用户输入该单词的正确拼写 如果用户输入正确的拼写 则会显示更正的单词以及错误的单词 下面 在读完所有单词之后 但是 如果用户只是按 Enter
  • SO_BINDTODEVICE Linux 套接字选项的问题

    我有一台带有两个网卡的电脑 一 eth0 用于 LAN 互联网 另一个用于与一个微控制器设备进行 UDP 通信 微控制器有一个 IP 192 168 7 2 和一个 MAC 地址 第二个电脑网络适配器 eth1 有 192 168 7 1
  • SO_REUSEPORT 可以在 Unix 域套接字上使用吗?

    Linux 内核 gt 3 9 允许通过设置在内核负载平衡的进程之间共享套接字SO REUSEPORT http lwn net Articles 542629 http lwn net Articles 542629 这如何用于类型的套接
  • 确定 TCP Listen() 队列中当前积压的连接数

    有没有办法找出currentLinux 上 TCP 套接字上等待 Accept 的连接尝试次数 我想我可以在每个事件循环上点击 EWOULDBLOCK 之前计算成功的 Accept 数量 但我使用的是隐藏这些细节的高级库 Python Tw
  • Qt 嵌入式触摸屏 QMouseEvents 在收到 MouseButtonRelease 之前未收到

    我在带有触摸屏的小型 ARM 嵌入式 Linux 设备上使用 Qt 4 8 3 我的触摸屏配置了 tslib 并对其进行了校准 因此 etc 中有一个 pointcal 文件 我的触摸事件的位置工作得很好 但无论如何我都会在鼠标按下或鼠标释
  • 选择fasta文件中氨基酸超过300个且“C”出现至少4次的序列

    我有一个包含蛋白质序列的 fasta 文件 我想选择超过 300 个氨基酸且半胱氨酸 C 氨基酸出现超过 4 次的序列 我使用此命令来选择具有超过 300 个 aa 的序列 cat 72hDOWN fasta fasta bioawk c
  • 应用程序中两个不同版本的库

    考虑一个场景 其中有两个不同版本的共享库 考虑 A 1 so 链接到 B so A 2 so 链接到 C so 现在 B so 和 C so 都链接到 d exe 当 B so 想要调用 A 1 so 中的函数时 它最终会调用 A 2 so
  • 如何将一个文本文件拆分为多个 *.txt 文件?

    我有一个文本文件file txt 12 MB 包含 something1 something2 something3 something4 有没有办法分开file txt分成 12 个 txt 文件 比方说file2 txt file3 t
  • Linux中如何避免sleep调用因信号而中断?

    我在 Linux 中使用实时信号来通知串行端口中新数据的到达 不幸的是 这会导致睡眠呼叫在有信号时被中断 有人知道避免这种行为的方法吗 我尝试使用常规信号 SIGUSR1 但我不断得到相同的行为 来自 nanosleep 联机帮助页 nan
  • 在ubuntu中打开spyder

    我想在ubuntu中打开spyder Python IDE 通常我会在 shell 中编写 spyder 它会打开spyder IDE 现在 当我在shell中编写spyder时 它只是换行 什么也没有发生 类似于按 enter 我如何找回
  • 更新Linux中的包含路径

    我的 my path to file 文件夹中有几个头文件 我知道如何将这些文件包含在新的 C 程序中 但每次我都需要在包含它之前输入头文件的完整路径 我可以在linux中设置一些路径变量 以便它自动查找头文件吗 您可以创建一个 makef
  • MySQL 与 PHP 的连接无法正常工作

    这是我的情况 我正在尝试使用 Apache 服务器上的 PHP 文件连接到 MySQL 数据库 现在 当我从终端运行 PHP 时 我的 PHP 可以连接到 MySQL 数据库 使用 php f file php 但是当我从网页执行它时 它只
  • Docker忽略limits.conf(试图解决“打开文件太多”错误)

    我正在运行一个 Web 服务器 该服务器正在处理数千个并发 Web 套接字连接 为了实现这一点 在 Debian linux 我的基本镜像是 google debian wheezy 在 GCE 上运行 上 打开文件的默认数量设置为 100
  • Linux shell 从用户输入中获取设备 ID

    我正在为一个程序编写安装脚本 该程序需要在其配置中使用 lsusb 的设备 ID 因此我正在考虑执行以下操作 usblist lsusb put the list into a array for each line use the arr
  • “git add”返回“致命:外部存储库”错误

    我刚刚进入 git 的奇妙世界 我必须提交我对程序所做的一系列更改 位于名为的目录中 var www myapp 我创建了一个新目录 home mylogin gitclone 从这个目录中 我做了一个git clone针对公共回购 我能够
  • 如何并行执行4个shell脚本,我不能使用GNU并行?

    我有4个shell脚本dog sh bird sh cow sh和fox sh 每个文件使用 xargs 并行执行 4 个 wget 来派生一个单独的进程 现在我希望这些脚本本身能够并行执行 由于某些我不知道的可移植性原因 我无法使用 GN
  • Linux 使用 boost asio 拒绝套接字绑定权限

    我在绑定套接字时遇到问题 并且以用户身份运行程序时权限被拒绝 这行代码会产生错误 acceptor new boost asio ip tcp acceptor io boost asio ip tcp endpoint boost asi

随机推荐

  • 数字图像处理之浮雕效果——基于傅里叶变换的频域操作

    问题简述 这是信号与系统课程的一个课后作业 要求运用傅里叶变换的理论知识 在matlab中对数字图像进行浮雕效果的处理 浮雕效果和图像边缘的检测差不多 学习过深度学习的同学可能会想到使用核对图像进行卷积操作 吴恩达老师在DeepLearni
  • Python之字典一个key对应多个value

    python的字典是一个key对应一个value 如果想要一个key对应多个value 那么可以用以下几种方法来实现 方法一 创建key对应列表 name list Mary Jack age list 10 12 stu dict nam
  • C++中 语句 #ifndef …详解

    C 中 语句 ifndef define endif 其作用是防止头文件的重复包含和编译 如果被定义则返回假 如果没有被定义则返回真 需要注意的是 ifndef起到的效果是防止一个源文件两次包含同一个头文件 而不是防止两个源文件包含同一个头
  • spark streaming job监控

    定时检查spark streaming job 运行状态保存到mysql中 1 python3保存数据到mysql vi rlt log job dinc py import pymysql import logging import pa
  • ansys选择一个面上所有节点_利用APDL命令选择椭球面上的节点

    微信公众号 CAE技术分享 问题的背景 笔者在利用Workbench的二次开发功能实现某模型的参数化建模 分网 加载时 由于workbench开发接口的限制 需要结合DM模块 MAPDL模块 Mesh模块 FEM模块以及Mechnical模
  • ELK日志分析系统原理与部署

    文章目录 一 ELK日志分析系统简介 1 1ELK日志分析系统组成 1 2日志处理步骤 二 三款软件各自概念 2 1Elasticsearch介绍 2 2Logstash介绍 2 3Kibana介绍 三 ELK日志分析系统部署 3 1实验环
  • Leetcode刷题之回文链表和交换链表中的结点

    竭力履行你的义务 你应该就会知道 你到底有多大的价值 列夫 托尔斯泰 目录 一 回文链表 1 快慢指针 2 把值存入数组中 然后使用双指针 二 交换链表中的结点 1 快慢指针 一 回文链表 给你一个单链表的头节点 head 请你判断该链表是
  • Spring 框架中都用到了哪些设计模式

    1 工厂模式 BeanFactory就是简单工厂模式的体现 用来创建对象的实例 2 单例模式 Bean默认为单例模式 3 代理模式 Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术 4 模板方法 用来解决代码重复的问
  • Python:Docx文档模板创建使用

    博文作者 wangzirui32 喜欢的可以 点赞 收藏 关注哦 本文首发于CSDN 未经许可禁止转载 Hello 大家好 我是wangzirui32 今天我们来学习Docx文档模板创建与使用 开始学习吧 1 Docxtpl Docxtpl
  • 服务器加cpu显示broadwell,英特尔新的Broadwell Xeon服务器CPU每个插槽可提供多达22个内核...

    英特尔的主流消费类处理器主要是双核和四核处理器 但是服务器CPU的性能要高得多 恰当的例子 基于Broadwell的新型Xeon E5 2600 v4系列中最昂贵的成员具有高达22个内核 运行频率为2 2GHz 而所有这些内核都只能装在一个
  • java中html网页转化成pdf(itext)

    Java 实现 HTML 页面转 PDF 解决方案 一 添加 maven 依赖
  • Centos for arm64 aarch64 下载地址列表以及鲲鹏服务器安装教程

    鲲鹏服务器安装Centos 7 6教程 镜像下载地址 一 BIOS 配置 二 通过BMC界面的虚拟光驱安装 1 虚拟光驱挂载系统ISO镜像 2 设置启动项为光驱启动 3 重启服务器 三 下载驱动软件包和驱动配套表 1 驱动下载 2 驱动安装
  • LeetCode 523. Continuous Subarray Sum 解题报告

    LeetCode 523 Continuous Subarray Sum 解题报告 题目描述 Given a list of non negative numbers and a target integer k write a funct
  • Oracle重命名sys或system操作记录

    oracle等保中有条要求 应重命名或删除默认账户 修改默认账户的默认口令 给的建议是修改sys system默认账户名称 避免使用常见用户名称 以下记录了两种方法来实现上面的要求 Oracle重命名sys操作记录 方法一 通过用户的信息是
  • android 手机获取是否开启了底部导航栏兼容小米、华为

    TargetApi Build VERSION CODES JELLY BEAN MR1 public static boolean isNavigationBarShow WindowManager windowManager Displ
  • Qt5.9调用Windows的匿名管道总结

    匿名管道一般用于两个父子进程之间的通信 通常是在MFC上调用 在Windows上 匿名管道的调用函数为CreatePipe 具体的原理讲解和调用实例 可以参考博主的这篇博客 https blog csdn net naibozhuan374
  • Python爬虫学了几个月却不敢接单?过来人的经验总结收好!

    前几天有刷到一个提问 爬虫学了几个月了却还是不敢上手去接单 爬虫接单靠不靠谱 有些新手心里会犯嘀咕 怕不小心就踩了红线 作为过来人也接过不少单 来浅聊一下我的经验 这篇所说的经验总结可能更适合爬虫新手 爬虫大佬可以忽略 此篇小结 Pytho
  • git拉取项目、提交代码简单教程

    最近要用HBuilderX做一个uniapp项目 再写一篇git拉项目代码 交代码的文章 虽然和上一篇差不多啦 不过就是上一篇的交代码没有用指令 这一篇就用一下 首先是要装好git和node 可以自行查找教程 应该没什么坑 第一步 新建一个
  • Vue3国际化适配(i18n)的简单使用(非常简单)

    Vue i18n是Vue js的国际化插件 Vue i18n官网 Vue I18n Vue I18n 下载Vue i18n插件 npm方式 npm install vue i18n 9 yarn方式 yarn add vue i18n 9
  • Linux系统编程项目——FTP云盘

    文章目录 一 项目实现功能 二 项目实现思路 三 项目用到的函数 1 access函数 判断文件是否存在的函数 2 chdir函数 进入某个文件夹的函数 3 fgets函数 可以获取空格 且较为安全 四 代码 五 项目总结 遇到的问题 一