网络编程-流

news/2024/5/3 13:08:55/文章来源:https://blog.csdn.net/weixin_50866517/article/details/126822328

  • 一、概貌
  • 1.消息类型
    • 二、getmsg和putmsg函数
      • 三、getpmsg和putpmsg函数
      • 四、ioctl函数
      • 五、TPI:传输提供者接口
  • 1.TPI时间获取客户程序

一、概貌

  1. 在进程和驱动程序(driver)之间提供全双工的连接,如下所示,虽然我们称底部那个方框为驱动程序,它却不必与某个硬件设备相关联,也就是说它可以是一个伪设备驱动程序(即软件驱动程序)

在这里插入图片描述
2. 流头由一些内核例程构成,应用进程针对流描述符执行系统调用(例如read、 putmsg、ioctl等)时这些内核例程将被激活。

  1. 进程可以在流头和驱动程序之间动态增加或删除中间处理模块,这些模块对顺褚一个流上行或下行的消息施行某种类型的过滤。如下所示:
    在这里插入图片描述
  2. 往一个流中可以推入任意数量的模块。我们说推入“意指每个新模块都被插入到流头的紧下方”。
    5.。多路复用器是一种特殊类型的伪设备驱动程序,从多个源接受数据。(SVR4中TCP/IP协议族基于流的实现图如下所示,包含多个多路复选器。)

在这里插入图片描述

  1. 在创建一个套接字时,套接字函数库把模块sockmod推入中。向应用进程提供套接字API的正是套接字函数库sockrnod流模块两者的组合。

  2. 在创建一个XTI端点时,XTI函数库模块timod推入中。向应用进程提供XTIAPI的正是XTI函数库timod流模块两者的组合。XTI API的端点相当于套接字API的套接字。

  3. 为了针对XTI端点使用read和write访间网络数据,通常必须把模块tirdwr推入流中。图中中间那个使用TCP的进程就是这么做的。推入该模块后XTI函数库中的函数不能继续使用,那个进程这么做也许已经放弃使用XTI,因此我们没给它标上XTI函数库。

  4. 所标的三个服务接口定义顺着流上行和下行交换的网络消息的格式。传输提供者接口TIP定义了向它上方的模块提供的接口。网络提供者接口NPI定义了网络提供者向它上方的模块提供的接口。DLPI数据链路层接口

一个流中的每个部件:流头所有处理模块驱动程序包含至少一对队列(queue):一个写队列和一个读队列,如下所示:

在这里插入图片描述

1.消息类型

  1. 流消息可划分为高优先级、优先级带和普通三类。优先级共有 256带,在0- 255之间取值,其中普通消息位于带0。流消息的优先级用于排队和流揽控制。按约定高优先级消息不受流量控制影响。

  2. 虽然流系统支持 256个不同的优先级带,网络协议往往只用代表经加速数据的带1和代表普通数据的带0。

  3. TPI不认为TCP带外数据是真正的经加速数据 ,事实上TCP的各通数据和带外数据都使用带0,只有那些让经加边数据(并不是像TCP中的紧急指针而已)先于普通数据发送的协议才使用带1发送经加速数据 。
    在这里插入图片描述
    普通优先级消息和高优先级消息两大类,它们却分别约有 12种和18种。有3种不同类型的消息: M_DATA、M_PROTO和M_PCPROTO (PC表示, 优先级控制,隐指高优先级消息)。下图 说明了这3种消息类型是如何使用write和putmsg这两个函数产生的。

在这里插入图片描述

二、getmsg和putmsg函数

//沿着流上行和下行的数据由消息构成,而且每个消息含有控制或数据亦或两者都有。
//如果在流上使用read和write。 那么所传送的仅仅是数据。
//下面两个函数提供进程能够读写数据和控制两部分信息
#include<stropts.h>
int getmsg(int fd,struct strbuf *ctlptr,struct strubf *dataptr,int *flagsp);
//最后一个参数是值-结果参数。
//flagsp指向的整数值为0 ,那么返回的是流中第一个消息(既可能是普通消息,也可能是高优先级消息)。
//该整数值为RS_HIPRI. 那就等待一个高优先级消息到达流头。
//无论哪种情况,存放到如flagsp指向的整数中的值根据所返回消息的类型或为0, 或为RS_HIPRI。
//传递给ctlptr和dataptr参数均为非空指针,如果没有控制信息待返回(也就是即将返回一 个M_ DATA 消息),就在返回时把ctlptr->lenn设置为-1作为指示。
//类似地如果没有数据待返回就把 dataptr->len设投为-1。int putmsg(int fd,const struct struct strbuf *ctlptr,const struct struct strbuf *dataptr,int flags);
//可以发送控制信息和数据也可以同时发送两者。
//指示缺失控制信息把vtlptr参数指定空指针,也可以ctlptr->len设置为-1。
//同样手段设置dataptr参数用于指示缺失数据。
//flags:0表示普通消息,为RS_HIPRI表示高优先级消息。struct strbuf{int maxlen;int len;char *buf;
};//putmsg在成功时返回0 , 在出错时返回- 1。
//getmsg仅在整个消息完整返回给调用者时才返问0 。
//如果控制缓冲区不足以容纳完整的控制信息,那就返回非负的MORECTL。
//类似地如果数据缓冲区太小,那就返回MOREDATA 。
//如果两个缓冲区都太小,那就返回这两个标志的逻缉或。

缺失控制信息,putmsg将产生一个M_DATA信息,如下所示。否则根据flags产生一个M_PROTO或M_PCRROTO消息。

在这里插入图片描述

三、getpmsg和putpmsg函数

当对于不同优先级带的支持随 SVR 4 被增加到流系统时,以下两个g e tm sg和pu tm sg 的变体函数也被间时引入。

#include<stropts.h>
int getpmsg(int fd,struct strbuf *ctlptr,struct strubf *dataptr,int *bandp,int *flagsp);
//bandp和flagsp参数是值-结果参数。
//flagsp指向的整数可以取值MSG_HIPRI(以读入一 个高优先消息)、MSG_BAND (以读入 一个优先级至少为bandp指向的整数值的消息)或MSG_ANY(以读入任一消息)。
//函数返回时,bandp指向的整数含有所读入消息的优先级带。
//flagsp指向的整数含有MSG_HIPRI (如果所读入的是一个商优先级消息)或MSG_BAND (如果所读入的是其他类型消息)。int putpmsg(int fd,const struct struct strbuf *ctlptr,const struct struct strbuf *dataptr,int band,int flags);
//band参数必须在0-255之间(含)。
//如果flags参数为MSG_BAND,那就产生一个所指定优先级带的消息。
//把flags设置为MSG_BAND并且把band设置设为0等效于调用putmsg。
//如果flags为MSG_HIPRI, ban就必须为0, 所产生的是 一个环优先级消息。(注意,putmsg使用不同名字的RS_HIPRI标志)。

四、ioctl函数

#include<stropts.h>
int ioctl(int fd,int request,.../*void *arg*/);
//处理流所必须包含的头文件不一样。

五、TPI:传输提供者接口

  1. TPI表示为传输层向它上方的模块提供的服务接口。在流环境中套接字和XTI都使用TPI。应用进程跟TCP和UD P交换TPI消息的是套接字函数库和sockmod的组合,或者是XTI函数库和tirnod的组合。

  2. TPI是一 个基于消息的接口。它定义了在应用进程 (例如XTI函数库或套接字函数库)和传输层之间沿看流上行和下行交换的消息,包括消息的格式和每个消息执行的操作。

  3. 实例中,应用进程向提供者发出 一 个请求 ( “捆绑这个本地地址"), 提供者则发回一个响应(“成功 ” 或 “出错”)。一些事件在提供者异步地发生 (对某个服务器的连接请求的到达),它们导致沿着流向上发送的消息或信号。我们可以绕过XTI和套接字直接使用TPI。

1.TPI时间获取客户程序

头文件tpi_daytime.h头文件

#include	"unpxti.h"
#include	<sys/stream.h>
#include	<sys/tihdr.h>void	tpi_bind(int, const void *, size_t);
void	tpi_connect(int, const void *, size_t);
ssize_t	tpi_read(int, void *, size_t);
void	tpi_close(int);

时间获取客户程序的mian函数:

#include	"tpi_daytime.h"int main(int argc, char **argv)
{int					fd, n;char				recvline[MAXLINE + 1];struct sockaddr_in	myaddr, servaddr;if (argc != 2)err_quit("usage: tpi_daytime <IPaddress>");
//打开传输提供者,绑定本地地址fd = open(XTI_TCP, O_RDWR, 0);
//填写服务器地址,建立连接/*4bind any local address */bzero(&myaddr, sizeof(myaddr));myaddr.sin_family = AF_INET;myaddr.sin_addr.s_addr = htonl(INADDR_ANY);myaddr.sin_port = htons(0);tpi_bind(fd, &myaddr, sizeof(struct sockaddr_in));/*4fill in server's address */bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port   = htons(13);	/* daytime server */inet_pton(AF_INET, argv[1], &servaddr.sin_addr);tpi_connect(fd, &servaddr, sizeof(struct sockaddr_in));
//从服务器读入数据,复制到标准输出for ( ; ; ) {if ( (n = tpi_read(fd, recvline, MAXLINE)) <= 0) {if (n == 0)break;elseerr_sys("tpi_read error");}recvline[n] = 0;		/* null terminate */fputs(recvline, stdout);}tpi_close(fd);exit(0);
}

tpi_bind函数:

#include	"tpi_daytime.h"void tpi_bind(int fd, const void *addr, size_t addrlen)
{struct {struct T_bind_req	msg_hdr;char				addr[128];} bind_req;/*
struct T_bind_req{t_scalar_t PRIM_type;t_scalar_t ADDR_length;t_scalar_t ADDR_offset;t_scalar_t CONIND_number;
};*/struct {struct T_bind_ack	msg_hdr;char				addr[128];} bind_ack;struct strbuf		ctlbuf;struct T_error_ack	*error_ack;int					flags;
//填写T_bind_req结构bind_req.msg_hdr.PRIM_type = T_BIND_REQ;//T_BIND_REQ或T_ERROP_ACKbind_req.msg_hdr.ADDR_length = addrlen;bind_req.msg_hdr.ADDR_offset = sizeof(struct T_bind_req);bind_req.msg_hdr.CONIND_number = 0;memcpy(bind_req.addr, addr, addrlen);	/* sockaddr_in{} */ctlbuf.len = sizeof(struct T_bind_req) + addrlen;ctlbuf.buf = (char *) &bind_req;putmsg(fd, &ctlbuf, NULL, 0);ctlbuf.maxlen = sizeof(bind_ack);ctlbuf.len = 0;ctlbuf.buf = (char *) &bind_ack;flags = RS_HIPRI;getmsg(fd, &ctlbuf, NULL, &flags);/* *INDENT-OFF* */if (ctlbuf.len < (int) sizeof(long))err_quit("bad length from getmsg");
/* *INDENT-ON* */switch(bind_ack.msg_hdr.PRIM_type) {case T_BIND_ACK:return;case T_ERROR_ACK:
/* *INDENT-OFF* */if (ctlbuf.len < (int) sizeof(struct T_error_ack))err_quit("bad length for T_ERROR_ACK");error_ack = (struct T_error_ack *) &bind_ack.msg_hdr;err_quit("T_ERROR_ACK from bind (%d, %d)",error_ack->TLI_error, error_ack->UNIX_error);
/* *INDENT-ON* */default:err_quit("unexpected message type: %d", bind_ack.msg_hdr.PRIM_type);}
}/*T_BIND_REQ或T_ERROP_ACK应答消息的结构:
struct T_bind_ack{t_scalar_t PRIM_type;t_scalar_t ADDR_length;t_scalar_t ADDR_offset;t_scalar_t CONIND_number;
};struct T_error_ack{t_scalar_t PRIM_type;t_scalar_t ADDR_prim;t_scalar_t ADDR_error;t_scalar_t UNIX_error;
};
*/

tpi_connect建立与服务器连接

#include	"tpi_daytime.h"void tpi_connect(int fd, const void *addr, size_t addrlen)
{struct {struct T_conn_req	msg_hdr;char				addr[128];} conn_req;struct {struct T_conn_con	msg_hdr;char				addr[128];} conn_con;
/*T_conn_con存放1连接的协议地址和选项:
struct T_conn_req{t_scalar_t PRIM_type;t_scalar_t DEST_length;t_scalar_t DEST_offset;t_scalar_t OPT_length;t_scalar_t OPT_offset;
};
*/struct strbuf		ctlbuf;union T_primitives	rcvbuf;struct T_error_ack	*error_ack;struct T_discon_ind	*discon_ind;int					flags;
//填写请求结构并发送给提供者conn_req.msg_hdr.PRIM_type = T_CONN_REQ;conn_req.msg_hdr.DEST_length = addrlen;conn_req.msg_hdr.DEST_offset = sizeof(struct T_conn_req);conn_req.msg_hdr.OPT_length = 0;conn_req.msg_hdr.OPT_offset = 0;memcpy(conn_req.addr, addr, addrlen);	/* sockaddr_in{} */ctlbuf.len = sizeof(struct T_conn_req) + addrlen;ctlbuf.buf = (char *) &conn_req;putmsg(fd, &ctlbuf, NULL, 0);
//读入响应ctlbuf.maxlen = sizeof(union T_primitives);ctlbuf.len = 0;ctlbuf.buf = (char *) &rcvbuf;flags = RS_HIPRI;getmsg(fd, &ctlbuf, NULL, &flags);
/*
struct T_ok_ack{t_scalar_t PRIM_type;t_scalar_t CORRECT_prim;
};*//* *INDENT-OFF* */if (ctlbuf.len < (int) sizeof(long))err_quit("tpi_connect: bad length from getmsg");
/* *INDENT-ON* */switch(rcvbuf.type) {case T_OK_ACK:break;case T_ERROR_ACK:
/* *INDENT-OFF* */if (ctlbuf.len < (int) sizeof(struct T_error_ack))err_quit("tpi_connect: bad length for T_ERROR_ACK");error_ack = (struct T_error_ack *) &rcvbuf;err_quit("tpi_connect: T_ERROR_ACK from conn (%d, %d)",error_ack->TLI_error, error_ack->UNIX_error);
/* *INDENT-ON* */default:err_quit("tpi_connect: unexpected message type: %d", rcvbuf.type);}
//等待连接ctlbuf.maxlen = sizeof(conn_con);ctlbuf.len = 0;ctlbuf.buf = (char *) &conn_con;flags = 0;getmsg(fd, &ctlbuf, NULL, &flags);/* *INDENT-OFF* */if (ctlbuf.len < (int) sizeof(long))err_quit("tpi_connect2: bad length from getmsg");
/* *INDENT-ON* *//*
struct T_conn_con{t_scalar_t PRIM_type;t_scalar_t RES_length;t_scalar_t RES_offset;t_scalar_t OPT_length;t_scalar_t OPT_offset;
};*/switch(conn_con.msg_hdr.PRIM_type) {case T_CONN_CON:break;/*
struct T_discon_ind{t_scalar_t PRIM_type;t_scalar_t DISCON_reason;t_scalar_t SEQ_number;
};case T_DISCON_IND:
/* *INDENT-OFF* */if (ctlbuf.len < (int) sizeof(struct T_discon_ind))err_quit("tpi_connect2: bad length for T_DISCON_IND");discon_ind = (struct T_discon_ind *) &conn_con.msg_hdr;err_quit("tpi_connect2: T_DISCON_IND from conn (%d)",discon_ind->DISCON_reason);
/* *INDENT-ON* */default:err_quit("tpi_connect2: unexpected message type: %d",conn_con.msg_hdr.PRIM_type);}
}

tpi_read从流中读入数据:

#include	"tpi_daytime.h"ssize_t
tpi_read(int fd, void *buf, size_t len)
{struct strbuf		ctlbuf;struct strbuf		datbuf;union T_primitives	rcvbuf;int					flags;
//读取控制信息和数据;处理应答ctlbuf.maxlen = sizeof(union T_primitives);ctlbuf.buf = (char *) &rcvbuf;datbuf.maxlen = len;datbuf.buf = buf;datbuf.len = 0;flags = 0;getmsg(fd, &ctlbuf, &datbuf, &flags);if (ctlbuf.len >= (int) sizeof(long)) {if (rcvbuf.type == T_DATA_IND)return(datbuf.len);else if (rcvbuf.type == T_ORDREL_IND)return(0);elseerr_quit("tpi_read: unexpected type %d", rcvbuf.type);} else if (ctlbuf.len == -1)return(datbuf.len);elseerr_quit("tpi_read: bad length from getmsg");
}
#include	"tpi_daytime.h"void tpi_close(int fd)
{struct T_ordrel_req	ordrel_req;struct strbuf		ctlbuf;
//向对端发送顺序释放ordrel_req.PRIM_type = T_ORDREL_REQ;ctlbuf.len = sizeof(struct T_ordrel_req);ctlbuf.buf = (char *) &ordrel_req;putmsg(fd, &ctlbuf, NULL, 0);close(fd);

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

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

相关文章

02 最优化模型建立方法

1 什么是数学模型 数学模型是关于部分现实世界和为一种特殊目的而作地一个抽象地.简化地结构。 具体就是为了某种目的&#xff0c;用字母.数字及其他数学符号建立起来地等式或不等式以及图表。图像。框图等描述客观事物的特征及内在联系的数学结构表达式。 2.建立数学模型的方…

【Linux---02】CentOS操作系统的说明「简单使用 | 文件目录 | 常用命令」

文章目录1. CentOS的简单使用2. CentOS的文件目录2.1 目录结构2.2 各个目录的含义3. CentOS的常用命令1. CentOS的简单使用 鼠标进入虚拟机的OS&#xff1a;直接点击鼠标左键 鼠标退出虚拟机的OS&#xff1a;ctrl alt 在linux系统上&#xff0c;不使用图形化终端&#xff0c…

蓝牙BLE调试关于NRF connect相关信息分析

简介 nRF Connect是一个强大的通用工具&#xff0c;它允许你扫描和探索你的蓝牙低功耗(以后的蓝牙LE&#xff0c;也称为蓝牙4.0版本的蓝牙规范)设备&#xff0c;并与它们通信。 nRF连接还允许您的iOS设备广告作为一个外围设备&#xff0c;充分支持许多蓝牙SIG采用的配置文件。…

微信小程序在线考试项目开发-用户信息注册登录功能

⭐️⭐️⭐️ 作者&#xff1a;船长在船上 &#x1f6a9;&#x1f6a9;&#x1f6a9; 主页&#xff1a;来访地址船长在船上的博客 &#x1f528;&#x1f528;&#x1f528; 简介&#xff1a;CSDN前端领域优质创作者&#xff0c;资深前端开发工程师&#xff0c;专注前端开发…

ERAT读和写指令(eratre和eratwe)

ERAT管理指令 为了使hypervisor&#xff08;或 “bare-metal” operating system&#xff09;软件可以直接操作ERAT的entries&#xff0c;在A2 core中实现一组nonarchitected的ERAT管理指令。为了防止user和guest模式下的程序影响TLB地址转换和访问控制机制&#xff0c;所有的E…

乐高广告创意50例——创意无砖

乐高的创意不仅仅局限于建造令人惊叹的建筑,或是拍摄定格电影,甚至是重新制作音乐专辑封面和电影海报,它甚至延伸到了广告领域。 与塑料砖一样,乐高可以采用最简单的概念,做出强大、智能且通常诙谐的声明。 从本图库中的精彩平面广告中,你可以看到,典型的乐高广告所采用…

《Python3 网络爬虫开发实战》:灵巧好用的 正则表达式

灵巧好用的 正则表达式 在上一节中&#xff0c;我们已经可以用 requests 来获取网页的源代码&#xff0c;得到 HTML 代码。但我们真正想要的数据是包含在 HTML 代码之中的&#xff0c;怎么才能从 HTML 代码中获取我们想要的信息呢&#xff1f;正则表达式就是其中一个有效的方法…

基于VC++的WEB浏览器的实现

目 录 摘 要 2 1设计题目与要求 2 2系统设计 2 2.1总体设计 2 2.2详细设计 2 2.2.1用户界面设计 3 2.2.2多标签模块设计 6 2.2.3浏览模块设计 6 2.2.4操作按钮模块设计 9 2.2.5页面缩放模块设计 10 2.2.6状态栏模块设计 11 2.2.7收藏夹模块设计 13 2.2.8窗体关闭模块设计 13 2.…

网页设计中蒸汽朋克的美丽例子

即使你不熟悉蒸汽朋克这个词,你无疑已经通过流行文化被介绍到了这种设计现象。蒸汽朋克指的是一种异想天开的风格,这种风格基于对19世纪可能的反乌托邦世界的想象。这听起来可能有点复杂,但这个折衷的类别将H.G.威尔斯的想法与维多利亚时代的设计、工业主义主题、后世界末日…

第3章 基础项目的搭建

3.1 后端项目搭建 3.1.1 gitee下载脚手架 下载地址&#xff1a;https://gitee.com/77jubao2015/springbootdemo 打开浏览器输入以上地址&#xff0c;点击下载即可&#xff0c;如图所示&#xff1a; 3.1.2 把脚手架导入到idea开发工具 步骤01 把下载后的脚手架放到指定位置并解…

数据库基本概念

目录 一、数据库概念 1、数据库的组成 &#xff08;数据为行&#xff0c;字段为列&#xff09; 2、数据库的管理系统&#xff08;DBMS) 二、数据库系统发展史 1、第一代数据库&#xff08;人工管理&#xff09; 2、第二代数据库&#xff08;文件管理&#xff09; 3、第三…

大学SQLServer2012 安装流程+启动+登录+用户的操作

这里写目录标题第一步下载解压的文件第二步骤安装软件第三步执行安装选项执行安装选项1执行安装选项2执行安装选项3 同意条款执行安装选项4配置检测执行安装选项5 下载需求组件执行安装选项6 上面安装完成后执行安装选项需求---关闭防火墙执行安装选项7--重新检测执行安装选项8…

SpringMVC基础:AJAX发送请求

AJAX请求 前面我们讲解了如何向浏览器发送一个JSON格式的数据&#xff0c;那么我们现在来看看如何向服务器请求数据。 Ajax即Asynchronous Javascript And XML&#xff08;异步JavaScript和XML&#xff09;&#xff0c;它的目标就是实现页面中的数据动态更新&#xff0c;而不是…

微服务--数据一致性

本篇文章讲解微服务数据一致性相关的知识 一、案例 在使用微服务时&#xff0c;存在跨多个服务更新数据库数据的情况。那么这就会出现一个问题&#xff0c;比如我们有三个服务&#xff08;如下图&#xff09;&#xff0c;正常情况下&#xff0c;当一个请求进来时&#xff0c;…

【软件与系统安全笔记】五、内存破坏防御

【软件与系统安全】五、内存破坏防御 这是《【软件与系统安全】笔记与期末复习》系列中的一篇 虽然对缓冲区溢出的认知已超过 40 年之久, 但缓冲区溢出仍未被消除。部分原因在于存在大量的利用选项&#xff1a; 多样的目标: 不仅仅可以利用返回地址, 实际上可以利用任意代码地…

JDK1.8中的Stream流源码中的常用方法全面解析附代码演示及源码展示

文章目录&#x1f4a8;更多相关知识&#x1f447;&#x1f342;allMatch&#x1f31f;代码演示&#x1f342;anyMatch&#x1f31f;代码演示&#x1f342;noneMatch&#x1f31f;代码演示&#x1f342;findFirst&#x1f31f;代码演示&#x1f342;findAny&#x1f31f;代码演示…

【愚公系列】2022年09月 微信小程序-WebGL纹理材质的使用

文章目录前言一、webgl的使用1.立体图形的绘制二、相关包源码三、总结前言 WebGL&#xff08;全写Web Graphics Library&#xff09;是一种3D绘图协议&#xff0c;这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起&#xff0c;通过增加OpenGL ES 2.0的一个JavaScrip…

[含毕业设计论文+PPT+源码等]ssm培训机构管理系统+Java后台管理系统|前后分离VUE

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 微信小程序项目介绍 资料获取 微信小程序项目介绍 计算机毕业设计java毕设项目之微信小程序ssm培训机构管理系统小程序后台管理系统_哔哩哔哩_bilibili计算机毕业设计java毕设项目之微信…

基于Springboot健身会员俱乐部管理系统设计

开发技术&#xff1a; Idea Springboot Mysql 功能描述&#xff1a; 1 系统管理员模块的具体需求如下&#xff1a; &#xff08;1&#xff09;会员管理:系统管理员在本系统中拥有对会员进行管理的功能。包括会员的注册、个人信息的修改、会员的删除、变更和查询&#xff0c…

Linux——权限

目录 Linux权限的概念 Linux权限管理 文件访问者的分类 文件类型和访问权限 文件类型 基本权限 文件权限值的表示方法 文件访问权限的相关设置方法 目录的权限 粘滞位 关于权限的总结 Linux权限的概念 Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;、…