【Linux--基础IO】

目录

  • 一、系统文件接口
    • 1.1 open
    • 1.2 write
    • 1.3 read
    • 1.4 close
  • 二、文件描述符
  • 三、文件描述符的分配规则
  • 四、重定向
    • 4.1输出重定向的原理
    • 4.2dup2函数的系统调用
  • 五、缓冲区
    • 5.1代码及现象
    • 5.2原理解释
    • 5.3C语言FILE
  • 六、文件系统
    • 6.1磁盘的介绍
    • 6.1磁盘的分区管理
  • 7、软硬连接
    • 7.1软连接
    • 7.2硬连接
    • 7.3区别
  • 八、Linux动静态库
    • 8.1了解动静态库
      • 8.1.1静态库的特点
      • 8.1.2动态库的特点
    • 8.2静态库的打包与使用
      • 8.2.1静态库的打包
      • 8.2.1静态库的使用
    • 8.3动态库的打包与使用
      • 8.3.1动态库的打包
      • 8.3.1动态库的打包
      • 8.3.2动态库的使用

一、系统文件接口

1.1 open

int open(const char* pathname,int flags,mode_t mode)

open的第一个参数
open函数的第一个参数是pathname,表示要打开或创建的目标文件

若pathname以路径的方式给出,则需要创建该文件时,在pathname路径下进行创建
若pathname以文件名的方式给出,则需要创建该文件时,默认在当前路径下进行创建
open的第二个参数
在这里插入图片描述
open函数的第三个参数
表示创建文件的默认权限
open的返回值
open函数成功调用后返回打开文件的文件描述符,若调用失败则返回-1。

1.2 write

Linux系统接口中使用write函数向文件写入信息

ssize_t write(int fd,const void* buf,size_t count)

将buf位置开始向后count字节的数据写入文件描述符为fd的文件当中。
若数据写入成功,则返回实际写入数据的字节数。
若数据写入失败,则返回-1。

1.3 read

inux系统接口中使用write函数向文件写入信息

ssize_t read(int fd,void* buf,size_t count)

从文件描述符为fd的文件读取count字节的数据到buf位置当中
若数据读取成功,则返回实际读取数据的字节数
若数据读取失败,则返回-1

1.4 close

使用close函数时传入需要关闭文件的文件描述符(即调用open函数的返回值)即可。若关闭文件成功则返回0;若关闭文件失败则返回-1。

int close(int fd)

二、文件描述符

在这里插入图片描述

三、文件描述符的分配规则

现象代码1:

#include <stdio.h>                                                                                                                                                               
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    int fd1 = open("./log1.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd2 = open("./log2.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd3 = open("./log3.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd4 = open("./log4.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd5 = open("./log5.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    printf("fd1: %d\n",fd1);
    printf("fd2: %d\n",fd2);
    printf("fd3: %d\n",fd3);
    printf("fd4: %d\n",fd4);
    printf("fd5: %d\n",fd5);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd5);
    return 0;
}

现象结果1:
在这里插入图片描述
现象代码2:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    close(0);
    close(2);                                                                                                                                                                    
    int fd1 = open("./log1.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd2 = open("./log2.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd3 = open("./log3.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd4 = open("./log4.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    int fd5 = open("./log5.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
    printf("fd1: %d\n",fd1);
    printf("fd2: %d\n",fd2);
    printf("fd3: %d\n",fd3);
    printf("fd4: %d\n",fd4);
    printf("fd5: %d\n",fd5);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd5);
    return 0;
}

现象结果2:
在这里插入图片描述
总结:文件描述符是从最小但是没有被使用的fd_array数组下标开始进行分配的

四、重定向

重定向包含了输入重定向、追加重定向、输出重定向。
其中的原理本质上都一样。

4.1输出重定向的原理

输出重定向的本质是,将本应该输出到A文件的数据输出到B文件中。
若想让本应该输出到"显示器文件"的数据输出到log.txt文件当中,可以在打开log.txt文件之前将文件描述符为1的文件关闭(即将“显示器文件”关闭)。当我们后续打开log.txt文件时所分配到的文件描述符就是1。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
	close(1);
	int fd = open("./log.txt",O_RDWR | O_CREAT | O_TRUNC, 0666);
    if(fd < 0){
        perror("opern error:");
        return 1;
    }
    printf("hello world\n");
	fflush(stdout);//为什么需要刷新?阅读后续章节《缓冲区》
	close(fd);
	return 0;
}

在这里插入图片描述

4.2dup2函数的系统调用

在Linux环境下还可以使用dup2()系统调用来实现重定向。dup2()本质上是通过fd_array数组中地址元素的拷贝完成重定向的。

#include <unistd.h>
int dup2(int oldfd, int newfd);

函数功能: 将fd_array[oldfd]的内容拷贝到fd_array[newfd]当中
函数返回值: 若调用成功则返回newfd,否则返回-1

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
	int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);
	if (fd < 0){
		perror("open");
		return 1;
	}
	close(1);
	dup2(fd, 1);
	printf("hello printf\n");
	fprintf(stdout, "hello fprintf\n");
	return 0;
}

在这里插入图片描述

五、缓冲区

5.1代码及现象

在这里插入图片描述

5.2原理解释

在这里插入图片描述

5.3C语言FILE

因为库函数是对系统调用接口的封装,本质上访问文件都是通过文件描述符fd进行访问的,所以C库当中的FILE结构体内部必定封装了文件描述符fd。
在/usr/include/stdio.h头文件中可以看到下面这句代码,也就是说FILE实际上就是struct _IO_FILE结构体的一个别名。

typedef struct _IO_FILE FILE;
struct _IO_FILE {
	int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
 
	//缓冲区相关
	/* The following pointers correspond to the C++ streambuf protocol. */
	/* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
	char* _IO_read_ptr;   /* Current read pointer */
	char* _IO_read_end;   /* End of get area. */
	char* _IO_read_base;  /* Start of putback+get area. */
	char* _IO_write_base; /* Start of put area. */
	char* _IO_write_ptr;  /* Current put pointer. */
	char* _IO_write_end;  /* End of put area. */
	char* _IO_buf_base;   /* Start of reserve area. */
	char* _IO_buf_end;    /* End of reserve area. */
	/* The following fields are used to support backing up and undo. */
	char *_IO_save_base; /* Pointer to start of non-current get area. */
	char *_IO_backup_base;  /* Pointer to first valid character of backup area */
	char *_IO_save_end; /* Pointer to end of non-current get area. */
 
	struct _IO_marker *_markers;
 
	struct _IO_FILE *_chain;
 
	int _fileno; //封装的文件描述符
#if 0
	int _blksize;
#else
	int _flags2;
#endif
	_IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
 
#define __HAVE_COLUMN /* temporary */
	/* 1+column number of pbase(); 0 is unknown. */
	unsigned short _cur_column;
	signed char _vtable_offset;
	char _shortbuf[1];
 
	/*  char* _save_gptr;  char* _save_egptr; */
 
	_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

在这里插入图片描述
在这里插入图片描述

六、文件系统

6.1磁盘的介绍

磁盘是一种永久性存储介质,在计算机中,磁盘几乎是唯一的机械设备,与磁盘相对应的就是内存,内存是掉电易失存储介质,目前所有的普通文件都是在磁盘中存储的。
在这里插入图片描述
磁盘中最基本的单元是扇区–512字节/4kb,可以把整个磁盘由无数个扇区组成。
要把数据存到磁盘中,首先要解决的定位扇区问题:
那一面(根据磁头Header)?哪个磁道Cylinder?哪个扇区Sector。
通过上面三个来定位扇区的方式又称为CHS寻址。
在这里插入图片描述

6.1磁盘的分区管理

计算机为了更好的管理磁盘,会对磁盘进行分区。而对于每一个分区来说,分区的头部会包括一个启动块(Boot Block),对于该分区的其余区域,EXT2文件系统会根据分区的大小将其划分为一个个的块组(Block Group).
在这里插入图片描述
如何理解创建一个空文件?
通过编列inode位图的方式,找到一个空间的inode
在inode Tbale中找到对应的inode,并将文件的属性信息填充到inode结构中。
将该文件的文件名与inode添加到目录文件的数据块中。
如何理解对文件写入信息?
通过文件的inode编号找到对应的inode结构。
通过inode结构找到存储该文件内容的数据块,并将数据写入到数据块
若不存在数据块或申请的数据块已经被写满,则通过遍历块位图的方式找到一个空闲的块号,并在数据块区当中找到对应的空闲块,再将数据写入数据块,最后将建立数据块与inode结构的对应关系。
如何理解删除一个文件?
将该文件对应的inode在inode位图当中置为无效。
将该文件申请过的数据块在块位图当中置为无效。
为什么拷贝文件的时候特别慢,而删除文件却特别块?
因为拷贝文件需要创建文件、然后对文件进行写入操作,这个过程需要先申请inode号然后填充文件的属性,再申请数据块,将文件内容写入到数据块最后建立数据块与inode结构的对应关系。
而删除文件只需要把对应的inode号与数据块在位图中设置无效即可。
如何理解目录?
目录也是文件,
目录有自己的属性信息,目录的inode结构当中存储的就是目录的属性信息,比如目录的大小,目录的拥有者等。
目录也有自己的内容,目录的数据块当中存储的就是该目录下的文件名以及对应文件的inode映射关系。

7、软硬连接

7.1软连接

在这里插入图片描述
软连接有独立的inode,也有独立的数据块,数据块的内容是指向的文件的路径。
软链接就类似于Windows操作系统当中的快捷方式。
在这里插入图片描述

但是软链接文件只是其源文件的一个标记,当删除了源文件后,链接文件不能独立存在,虽然仍保留文件名,但却不能执行或是查看软链接的内容了。

7.2硬连接

在这里插入图片描述
硬连接文件的inode号与源文件的inode号相同,并且文件的属性也相同。可以认为硬链接是源文件的别名,一个inode有几个文件名该inode的硬链接数就是多少

为什么刚创建的目录的硬链接数是2?
在这里插入图片描述
在这里插入图片描述

原因:每个目录创建后,该目录下默认会有两个隐含文件.和…,它们分别代表当前目录和上级目录。这个dir与.是一样的。

7.3区别

1.软链接是一个独立的文件,有独立的inode,而硬链接没有独立的inode。
2.软链接相当于快捷方式,硬链接本质没有创建文件,只是建立了一个文件名和已有的inode的映射关系,并写入当前目录。

八、Linux动静态库

8.1了解动静态库

一堆源文件和头文件最终变成一个可执行程序需要经历以下四个步骤:
1.预处理: 完成头文件展开、去注释、宏替换、条件编译等,最终形成xxx.i文件
2.编译: 完成词法分析、语法分析、语义分析、符号汇总等,检查无误后将代码翻译成汇编指令,最终形成xxx.s文件
3.汇编: 将汇编指令转换成二进制指令,最终形成xxx.o文件
4.链接: 将生成的各个xxx.o文件进行链接,最终形成可执行程序
实际上,所有库本质是一些目标文件(xxx.o)的集合,库的文件当中并不包含主函数而只是包含了大量的方法以供调用,可以认为动静态库本质是可执行程序的"半成品"

  • 在Linux当中,以.so为后缀的是动态库,以.a为后缀的是静态库
  • 在Windows当中,以.dll为后缀的是动态库,以.lib为后缀的是静态库
    通过ldd命令可以查看可执行程序所依赖的库文件
    在这里插入图片描述

根据上图可以看出来test可执行程序依赖/lib64/lib.so.6,本质上是一个软连接,链接的源文件是/lib64/libc-2.17.so。这个libc-2.17.so就是C的动态库,去掉库的前缀,再去掉后缀,剩下的就是库的名字。

而gcc/g++默认进行的是动态链接,想使用静态链接需添加 -static 选项,且静态链接生成的可执行程序并不依赖其他库文件。
在这里插入图片描述
而且 使用静态库的可执行程序的大小 明显大于 使用动态库的可执行程序的大小

8.1.1静态库的特点

静态库是程序在编译链接的时候把库的代码复制到可执行文件当中的,生成的可执行程序在运行的时候将不再需要静态库,因此使用静态库生成的可执行程序的大小一般比较大

  • 优点:使用静态库生成可执行程序后,该可执行程序可独自运行,不再依赖库了
  • 缺点:使用静态库生成可执行程序会占用大量空间,特别是当有多个静态程序同时加载而这些静态程序使用的都是相同的库,这时在内存当中就会存在大量的重复代码

8.1.2动态库的特点

动态库是程序在运行的时候才去链接相应的动态库代码的,不必将库的代码复制到可执行文件当中,使得可执行程序的大小较使用静态库而言更小,节省磁盘空间。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
在这里插入图片描述

在可执行文件开始运行前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接。操作系统采用虚拟内存机制使得物理内存中的一份动态库被所有要使用该库的进程共用,节省了内存空间。

8.2静态库的打包与使用

8.2.1静态库的打包

第一步:将打包的源文件生成对应的目标文件

func1.o:func1.c
    gcc -c func1.c -o func1.o
func2.o:func2.c
    gcc -c func2.c -o func2.o

在这里插入图片描述
第二步:使用ar命令将所有的目标文件打包成静态库

  • -r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件
  • (create):建立静态库文件
libfunc.a:func1.o func2.o
    ar -rc libfunc.a func1.o func2.o

在这里插入图片描述
此外,我们可以用ar命令的- t 和 -v 选项查看静态库当中的文件。

-t:列出静态库中的文件
-v(verbose):显示详细的信息
在这里插入图片描述
第三步:将头文件和生成的静态库组织

mkdir -p my_lib/include
mkdir -p my_lib/lib
cp ./*.h ./my_lib/include 
cp ./*.a ./my_lib/lib

在这里插入图片描述
makefile完整版

libfunc.a:func1.o func2.o
    ar -rc $@ $^
func1.o:func1.c
    gcc -c $^ -o $@
func2.o:func2.c
    gcc -c $^ -o $@
 
.PHONY:output
output:
    mkdir -p my_lib/include
    mkdir -p my_lib/lib
    cp ./*.h ./my_lib/include 
    cp ./*.a ./my_lib/lib
 
.PHONY:clean
clean:
    rm -rf ./my_lib ./*.o ./*.a      

8.2.1静态库的使用

方案一:使用选项

-I:指定头文件搜索路径
-L:指定库文件搜索路径
-l:指明需要链接库文件路径下的具体哪一个库
在这里插入图片描述
方案二:将头文件和库文件拷贝到系统路径下

sudo cp my_lib/include/* /usr/include/
sudo cp my_lib/libfunc.a /lib64/

实际上拷贝头文件和库文件到系统路径下的过程,就是安装库的过程。但并不推荐将个人编写的头文件和库文件拷贝到系统路径下,会对系统文件造成污染。所以我就不想演示这个过程了。

8.3动态库的打包与使用

8.3.1动态库的打包

第一步:将要打包的源文件生成对应的目标文件
此时需要添加 -fPIC 选项 ,即产生位置无关码

test1.o:test1.c
    gcc -fPIC -c test1.c -o test1.o
test2.o:test2.c
    gcc -fPIC -c test2.c -o test2.o

-fPIC作用于编译阶段,告诉编译器产生与位置无关的代码,此时产生的代码中没有绝对地址,全部都使用相对地址,从而代码可以被加载器加载到内存的任意位置都可以正确的执行(通过页表与共享区建立映射关系)。所以共享库被加载时,在内存的位置不是固定的 。
第二步:使用-shared选项将所有目标文件打包为动态库

libtest.so:test1.o test2.o
    gcc -shared $^ -o $@

第三步:组织头文件与生成的动态库

mkdir -p my_lib/include
mkdir -p my_lib/lib
cp ./*.h ./my_lib/include 
cp ./*.so ./my_lib/lib       

makefile完整版

 libtest.so:test1.o test2.o
    gcc -shared $^ -o $@
test1.o:test1.c
    gcc -fPIC -c test1.c -o test1.o
test2.o:test2.c
    gcc -fPIC -c test2.c -o test2.o
 
.PHONY:output
output:
    mkdir -p my_lib/include
    mkdir -p my_lib/lib
    cp ./*.h ./my_lib/include 
    cp ./*.so ./my_lib/lib                                                                                                                                                       
 
.PHONY:clean
clean:
    rm -rf *.so *.o my_lib

8.3.1动态库的打包

第一步:将要打包的源文件生成对应的目标文件

此时需要添加 -fPIC 选项 ,即产生位置无关码

func1.o:func1.c
    gcc -fPIC -c $@ -o $^
func2.o:func2.c
    gcc -fPIC -c $@ -o $^

-fPIC作用于编译阶段,告诉编译器产生与位置无关的代码,此时产生的代码中没有绝对地址,全部都使用相对地址,从而代码可以被加载器加载到内存的任意位置都可以正确的执行(通过页表与共享区建立映射关系)。所以共享库被加载时,在内存的位置不是固定的 。
第二步:使用-shared选项将所有目标文件打包为动态库

libtest.so:func1.o func2.o
    gcc -shared $^ -o $@

第三步:组织头文件与生成的动态库

mkdir -p my_lib/include
mkdir -p my_lib/lib
cp ./*.h ./my_lib/include 
cp ./*.so ./my_lib/lib       

makefile完整版

libtest.so:func1.o func2.o
    gcc -shared $^ -o $@
func1.o:func1.c
    gcc -fPIC -c $@ -o $^
func2.o:func2.c
    gcc -fPIC -c $@ -o $^
 
.PHONY:output
output:
    mkdir -p my_lib/include
    mkdir -p my_lib/lib
    cp ./*.h ./my_lib/include 
    cp ./*.so ./my_lib/lib                                                                                                                                                       
 
.PHONY:clean
clean:
    rm -rf *.so *.o my_lib

8.3.2动态库的使用

接下来使用与静态库相同的方式,用-I选项指定头文件搜索路径,用-L选项指定库文件搜索路径,最后用-l选项指明库的名称。但是可以发现可执行程序貌似找不到这个动态库的位置。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于FPGA的温度控制系统设计(论文+源码)

1.系统设计 本次基于FPGA的智能温度控制系统&#xff0c;以FPGA为控制核心&#xff0c;采用自顶向下的设计方法&#xff0c;按照模块化设计的思路分别实现各个模块&#xff0c;再加以整合实现整个系统&#xff0c;从而达到了温度控制的目的。系统以水箱为被控对象&#xff0c;…

【Spring 源码】 深入理解 Bean 定义之 BeanDefinition

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

Python文件操作(txt + xls + json)

文章目录 简介1、使用with_open读取和保存&#xff1a;.txt .bin&#xff08;二进制文本&#xff09;1.1、with open语句详解1.1、项目实战 2、使用pandas读取和保存&#xff1a;.xls .xlsx2.1、pandas简介2.2、环境配置2.3、项目实战 3、 使用json.dump读取和保存&#xff1…

如何查询川菜食材配料的API接口

在当今的美食文化中&#xff0c;菜谱不只是一张简单的食谱&#xff0c;更是了解美食文化和饮食知识的重要途径。然而&#xff0c;若没有准确的食材配料&#xff0c;烹制出的每道菜品都将难以达到完美的味道。因此&#xff0c;为了更好地满足人们对于菜谱和食谱的需求&#xff0…

Avalonia中如何实现文件拖拽上传

前言 前面我们讲了在Avalonia中如何将View事件映射到ViewModel层感兴趣的读者可以看一下&#xff0c;本章我们将讲一下在Avalonia框架下如何实现文件和文字的拖拽到指定区域进行处理和上传。 先看效果 界面设计比较简单&#xff0c;还是在前一张的基础上加了一个指定区域&…

Vue使用百度地图以及实现轨迹回放 附完整代码

百度地图开放平台 https://lbs.baidu.com/index.php?title%E9%A6%96%E9%A1%B5 javaScript API https://lbs.baidu.com/index.php?titlejspopularGL 百度地图实例 https://lbsyun.baidu.com/index.php?titleopen/jsdemoVue Baidu Map文档 https://dafrok.github.io/vue-baidu…

【环境搭建】ubuntu22安装ros2

基于某种特殊需求&#xff0c;从Ubuntu16到22目前都尝试过安装ros、ros2 参考1&#xff1a;http://t.csdnimg.cn/DzvSe 参考2&#xff1a;http://t.csdnimg.cn/sOzr1 1.设置locale sudo apt update && sudo apt install locales sudo locale-gen en_US en_US.UTF-8 s…

基于ssm vue协同过滤算法的图书推荐系统源码和论文

基于ssm vue协同过滤算法的图书推荐系统源码和论文742 idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 环境&#xff1a; jdk8 tomcat8.5 开发技术 ssm 摘 要 “互联网”的战略实施后&#xff0c;很多行业的信息化水平都有了很大的提升。但是目前很多行业…

[原创][6]探究C#多线程开发细节-“ConcurrentDictionary<T,T>解决多线程的无顺序性的问题“

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…

Matlab 点云曲线探测(算法不稳定,仅用于学习)

文章目录 一、简介二、实现代码三、实现效果参考文献一、简介 这是一个很有趣的曲线探测的方法,不过我没有复现出论文中那样的效果,可能是理解有误,但这个算法仍然是很有意思,故这里也对其进行记录。 按照论文中的思路,首先我们需要通过一种线性强度图来计算确定每个点的法…

学好操作系统需要的前置知识

1. 态度&#xff1a;不要等一切都准备好了再前行 如果把一切你可能会说&#xff0c;没有这些基础知识&#xff0c;我每看一篇文章&#xff0c;知识就铺天盖地席卷过来&#xff0c;仿佛每一个知识点都准确地打在了自己的盲点上&#xff0c;这该怎么办呢&#xff1f; 我非常能理…

一对多群聊

服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{public static ServerSocket server_socket;public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []args){try{…

第二十一章总结博客

网络程序设计基础 局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机。如下图所示 网络协议 1.IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmission …

Docker架构及常用的命令

一、初识Docker 1、 docker是一个快速交付应用、运行应用的技术&#xff0c;具备下列优势&#xff1a; 可以将程序及其依赖、运行环境一起打包为一个镜像&#xff0c;可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离容器&#xff0c;各个应用互不干扰启动、移除都可以…

linux搭建nacos集群

准备 检查是否安装jdk [roothao /usr/local/software/elk/logstash]# java -version java version "1.8.0_341" Java(TM) SE Runtime Environment (build 1.8.0_341-b10) Java HotSpot(TM) 64-Bit Server VM (build 25.341-b10, mixed mode)配置nacos 去github下载…

一文3000字从0到1用Python进行gRPC接口测试!

gRPC 是一个高性能、通用的开源RPC框架&#xff0c;其由 Google 主要面向移动应用开发并基于HTTP/2 协议标准而设计&#xff0c;基于 ProtoBuf(Protocol Buffers) 序列化协议开发&#xff0c;且支持众多开发语言。 自gRPC推出以来&#xff0c;已经广泛应用于各种服务之中。在测…

Vue2脚手架搭建+项目基础依赖安装

文章目录 1. 安装 node.js2. 安装 vue-cli 脚手架3. 创建 vue2 项目4. 安装基础依赖 1. 安装 node.js 可以参考这篇文章 https://blog.csdn.net/weixin_43721000/article/details/134284418 2. 安装 vue-cli 脚手架 安装 vue-clinpm install -g vue/cli查看是否安装成功vue -…

用23种设计模式打造一个cocos creator的游戏框架----(七)代理模式

1、模式标准 模式名称&#xff1a;代理模式 模式分类&#xff1a;结构型 模式意图&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。 结构图&#xff1a; ​ 适用于&#xff1a; 远程代理&#xff1a;也称为大使&#xff0c;这是最常见的类型&#xff0c;在分…

Data Mining数据挖掘—2. Classification分类

3. Classification Given a collection of records (training set) – each record contains a set of attributes – one of the attributes is the class (label) that should be predicted Find a model for class attribute as a function of the values of other attribu…

vuepress-----14、保护私密信息

秘钥存储文件 使用秘钥 忽略提交