day-03 基于TCP的服务器端/客户端
一.理解TCP和UDP
TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)是两种常见的传输层协议,用于在计算机网络中提供可靠的数据传输。
1.TCP:
- 连接导向:TCP是一种面向连接的协议,通信双方在数据传输前需要先建立可靠的连接。
- 可靠性:TCP提供可靠的数据传输,通过使用序列号、确认应答、超时重传等机制来确保数据的完整性和可靠性。
- 流量控制与拥塞控制:TCP通过流量控制和拥塞控制来调节发送端的数据发送速率,以避免网络拥堵或丢包现象。
- 有序性:TCP保证数据按照发送顺序到达目标端,不会发生乱序问题。
- 面向字节流:TCP将数据视为连续的字节流进行传输,没有消息边界的概念。
TCP适用于对数据完整性和可靠性要求较高的应用场景,如文件传输、电子邮件、网页浏览等。
2.UDP:
- 无连接:UDP是一种无连接的协议,通信双方在数据传输时不需要先建立连接。
- 不可靠性:相比TCP,UDP不提供数据的可靠性保证,数据可能会丢失、乱序或重复。
- 无拥塞控制:UDP不对数据发送速率进行调节,因此可能会造成网络拥堵和丢包现象。
- 无序性:UDP没有保证数据按照发送顺序到达目标端的机制,数据可能会乱序到达。
- 面向报文:UDP将数据视为独立的报文进行传输,保留了消息的边界。
UDP适用于对实时性要求较高、数据丢失可容忍或应用自身提供可靠性机制的应用场景,如音频/视频流传输、在线游戏等。
需要根据具体应用需求选择使用TCP还是UDP。TCP提供可靠的有序数据传输,适合对数据完整性要求较高的场景;而UDP提供了更低的延迟和更高的实时性,适用于对实时性要求较高、数据丢失可容忍的场景。
TCP/IP协议栈
二.实现基于TCP的服务器端/客户端
1.TCP服务器端的默认函数调用顺序
2.TCP客户端的默认函数调用顺序
3.基于TCP的服务器端/客户端函数调用关系
4.实现迭代回声服务器端/客户端
(VM ubuntu编译Cpp:g++ -std=c++11 文件名 -o 生成文件名)
(1)echo_server.cpp
- g++ -std=c++11 echo_server.cpp -o eserver
- ./eserver 9190
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024void error_handling(const char *message);int main(int argc, char *argv[]) {int serv_sock, clnt_sock;char message[BUF_SIZE];int str_len, i;struct sockaddr_in serv_adr, clnt_adr;socklen_t clnt_adr_sz;if (argc != 2) {std::cout << "Usage: " << argv[0] << " <port>" << std::endl;exit(1);}serv_sock = socket(PF_INET, SOCK_STREAM, 0);if (serv_sock == -1)error_handling("socket() error");memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);serv_adr.sin_port = htons(atoi(argv[1]));if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1)error_handling("bind() error");if (listen(serv_sock, 5) == -1)error_handling("listen() error");clnt_adr_sz = sizeof(clnt_adr);for (i = 0; i < 5; i++) {clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);if (clnt_sock == -1)error_handling("accept() error");elsestd::cout << "Connected client " << i+1 << std::endl;while ((str_len = read(clnt_sock, message, BUF_SIZE)) != 0)write(clnt_sock, message, str_len);close(clnt_sock);}close(serv_sock);return 0;
}void error_handling(const char *message) {std::cout << message << std::endl;exit(1);
}
(2)echo_client.cpp
- g++ -std=c++11 echo_client.cpp -o eclient
- ./eclient 127.0.0.1 9190
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024void error_handling(const char *message);int main(int argc, char *argv[]) {int sock;char message[BUF_SIZE];int str_len;struct sockaddr_in serv_adr;if (argc != 3) {std::cout << "Usage: " << argv[0] << " <IP> <port>" << std::endl;exit(1);}sock = socket(PF_INET, SOCK_STREAM, 0);if (sock == -1)error_handling("socket() error");memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = inet_addr(argv[1]);serv_adr.sin_port = htons(atoi(argv[2]));if (connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1)//调用conndect函数error_handling("connect() error!");elsestd::cout << "connected..........." << std::endl;while (true) {std::cout << "Input message (Q to quit): ";std::cin.getline(message, BUF_SIZE);if (strcmp(message, "q") == 0 || strcmp(message, "Q") == 0)break;write(sock, message, strlen(message));str_len = read(sock, message, BUF_SIZE-1);message[str_len] = '\0';std::cout << "Message from server: " << message << std::endl;}close(sock);//调用close函数向相应套接字发送EOF(EOF意味着中断连接)return 0;
}void error_handling(const char *message) {std::cerr << message << std::endl;exit(1);
}
存在问题:
- 如果数据量太大,操作系统可能把数据分成多个数据包发送到客户端(但是服务器端每次接收读取之后只调用一次 write() 函数。
- 另外,客户端有可能在尚未收到全部数据包时就调用 read()函数,导致回声不完整。
三.总结
1.说明TCP/IP的4层协议栈,并说明TCP和UDP套接字经过的层级结构差异。
TCP/IP协议栈是一个网络通信的基本模型,它由四层协议组成,分别是应用层、传输层、网络层和链路层。
-
应用层:应用层提供了用户与网络之间的接口,负责处理特定的应用程序数据。常见的应用层协议有HTTP、FTP、SMTP等。
-
传输层:传输层主要负责在网络中传输数据。其中最重要的两个协议是TCP(传输控制协议)和UDP(用户数据报协议)。
-
TCP套接字经过传输层。TCP是一种面向连接的协议,提供可靠的数据传输。它通过建立连接、数据分段、流量控制、拥塞控制等机制来保证数据的可靠性和顺序性。TCP套接字在传输层使用IP地址和端口号进行标识。
-
UDP套接字也经过传输层。UDP是一种无连接的协议,不提供可靠性保证。它将数据打包成数据报发送,不关心数据是否能够到达目标地址。UDP套接字同样使用IP地址和端口号进行标识。
-
-
网络层(IP层):网络层负责将数据从源主机传输到目标主机,它使用IP协议进行数据包的路由选择和转发。IP协议为数据包分配唯一的IP地址。
-
链路层:链路层是网络通信的物理层和数据链路层接口,负责将网络层传输的数据转换成比特流进行物理传输。它包括了物理寻址、帧封装和错误检测等功能。
- IP层和链路层之间的关系是协同工作。IP层将数据封装成IP数据包,在传输过程中会添加源IP地址和目标IP地址,然后将数据包交给链路层进行物理传输。链路层收到IP数据包后,会添加自己的帧头和帧尾信息,并将数据包转换成比特流发送。接收端的链路层会将接收到的比特流重新组装成帧,并去除链路层的头部和尾部信息,然后将数据包交给IP层进行进一步处理。
- 总结来说,IP层负责寻址、路由选择和数据包的传输控制,而链路层负责物理传输和错误检测。它们共同协作,完成了数据从源主机到目标主机的传输过程。
所以,TCP和UDP套接字在协议栈的层级结构上并无差异,都经过传输层。它们的主要区别在于TCP提供面向连接的可靠传输,而UDP提供无连接的不可靠传输。根据应用场景的需要,可以选择使用TCP或UDP来进行数据传输。
2.为什么要把TCP/IP协议栈分成4层(或7层)结合开放式系统回答?
TCP/IP协议栈被分成多层的设计是出于以下几个原因,其中也与开放式系统相关:
-
模块化设计:将TCP/IP协议栈分成多层可以实现模块化的设计,每一层都有明确定义的功能和责任。这样可以提高系统的可维护性和可扩展性。如果需要对某一层进行修改或替换,只需关注特定层而无需改动其他层。
-
逻辑分离:将网络通信过程划分为不同的层级,可以实现逻辑上的分离。每一层专注于自身的任务,不需要关心其他层的具体实现。这种分离使得各层之间的接口定义清晰,降低了系统的复杂性。
-
标准化和互操作性:将TCP/IP协议栈分成多层使得每一层的功能和协议得到标准化。这样不同厂商、不同操作系统的设备都可以按照相同的标准实现对应的层,从而实现互操作性。这种开放式的设计使得不同设备和系统能够无缝地进行通信。
-
灵活性和可定制性:通过分层设计,可以根据具体需求选择性地使用不同层提供的功能。例如,某些应用场景可能只需要传输层和网络层的功能,可以选择性地使用这些层,而不需要实现其他层。这种灵活性和可定制性使得TCP/IP协议栈适应各种不同的网络和应用需求。
综上所述,将TCP/IP协议栈分成多层结构是为了实现模块化设计、逻辑分离、标准化和互操作性,以及提供灵活性和可定制性。这样的设计使得开放式系统中的不同设备和系统能够相互通信,并且能够根据具体需求进行定制和扩展。
3.客户端调用connect函数向服务器端发送连接请求。服务器端调用哪个函数后,客户端可以调用connect函数?
服务器端调用 listen 函数后,客户端可以调用 connect 函数。
在TCP通信中,服务器端需要先调用listen函数来监听指定的端口,以便接受客户端的连接请求。listen函数使得服务器端处于监听状态,等待客户端连接。
一旦服务器端调用了listen函数,客户端就可以通过调用connect函数向服务器端发送连接请求。connect函数会建立与服务器端的连接,并进行三次握手来确保连接的可靠性。
所以,客户端需要在服务器端调用listen函数之后才能调用connect函数,以发起与服务器的连接。
4.什么时候创建连接请求等待队列,有何作用,和accept有什么关系?
连接请求等待队列是在服务器端调用listen
函数后创建的。它的作用是用于存储尚未被服务器端accept
函数接受的客户端连接请求。
当服务器端调用listen
函数后,它会开始监听指定的端口,并将该端口设置为监听状态,等待客户端的连接请求。如果有多个客户端同时向服务器端发送连接请求,而服务器端只能逐个处理这些请求,这时就需要使用连接请求等待队列。
连接请求等待队列允许服务器端在处理一个连接请求时,将其他连接请求暂时保存起来,以便后续处理。通过使用连接请求等待队列,可以确保当服务器端正在处理一个连接请求时,其他连接请求不会被丢失。
当服务器端调用accept
函数时,它从连接请求等待队列中取出一个连接请求进行处理。accept
函数会建立与客户端的连接,并返回一个新的套接字,服务器端可通过这个套接字与对应的客户端进行通信。
因此,连接请求等待队列与accept
函数密切相关。连接请求等待队列存储了尚未被接受的客户端连接请求,而accept
函数则负责从队列中取出连接请求并建立连接。通过连接请求等待队列和accept
函数的配合使用,服务器端能够管理和处理多个客户端的连接请求。
5.客户端中为何不需要调用bind函数分配函数地址,如果不调用bin函数,那么何时,如何向套接字分配IP地址和端口号?
在客户端中,不需要调用bind()
函数来分配函数地址,是因为客户端一般不需要绑定特定的IP地址和端口号。客户端的套接字可以通过操作系统自动分配可用的临时端口,并自动关联客户端的IP地址。
当客户端创建套接字时,操作系统会自动选择一个可用的本地端口,并将其与套接字进行关联。这个过程通常称为"隐式绑定"(implicit binding)。
隐式绑定可以确保客户端使用的本地端口是唯一的,并且不会与其他应用程序冲突。对于大多数客户端应用程序而言,这种自动分配是足够的,无需显式调用bind()
函数。
需要注意的是,如果你想要在客户端使用特定的本地IP地址和端口号,或者需要进行端口重用等特殊操作,那么你可能需要调用bind()
函数来手动指定这些参数。但一般情况下,客户端并不需要手动调用bind()
函数来分配函数地址。
四.回声客户端的功能实现(加减乘)----应用层协议设计
要求,服务器端从客户端获得多个数字和运算符信息,然后把结果传回客户端。
1.op_server.cpp
#include<iostream>
#include<cstring>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>#define BUF_SIZE 1024
#define OPSZ 4void error_handling(const char *message);
int calculate(int opnum,int opnds[],char oprator);int main(int argc,char *argv[]){int serv_sock,clnt_sock;char opinfo[BUF_SIZE];int result,opnd_cnt,i;int recv_cnt,recv_len;struct sockaddr_in serv_adr,clnt_adr;socklen_t clnt_adr_sz;if(argc!=2){std::cout<<"Usage :"<<argv[0]<<"<port>"<<std::endl;exit(1);}serv_sock=socket(PF_INET,SOCK_STREAM,0);if(serv_sock==-1)error_handling("socket() error");memset(&serv_adr,0,sizeof(serv_adr));serv_adr.sin_family=AF_INET;serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);serv_adr.sin_port=htons(atoi(argv[1]));if(bind(serv_sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)error_handling("bind() error");if(listen(serv_sock,5)==-1)error_handling("listen() error");clnt_adr_sz=sizeof(clnt_adr);for(i=0;i<5;i++){opnd_cnt=0;//运算个数clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,&clnt_adr_sz);read(clnt_sock,&opnd_cnt,1);recv_len=0;while((opnd_cnt*OPSZ+1)>recv_len){//读取运算值recv_cnt=read(clnt_sock,&opinfo[recv_len],BUF_SIZE-1);recv_len+=recv_cnt;}result+=calculate(opnd_cnt,(int*)opinfo,opinfo[recv_len-1]);write(clnt_sock,(char*)&result,sizeof(result));close(clnt_sock);//当前客户端结束后关闭}close(serv_sock);return 0;
}int calculate(int opnum,int opnds[],char op){//功能函数int result=opnds[0],i;switch(op){case '+':for(i=1;i<opnum;i++) result+=opnds[i];break;case '-':for(i=1;i<opnum;i++) result-=opnds[i];break;case '*':for(i=1;i<opnum;i++) result*=opnds[i];break;}return result;
}void error_handling(const char*message){std::cout<<message<<std::endl;exit(1);
}
2.op_client.cpp
#include<iostream>
#include<cstring>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>#define BUF_SIZE 1024
#define RLT_SIZE 4
#define OPSZ 4void error_handling(const char *message);int main(int argc,char *argv[]){int sock;char opmsg[BUF_SIZE];int result,opnd_cnt,i;struct sockaddr_in serv_adr;if(argc!=3){std::cout<<"Usage:"<<argv[0]<<"<IP> <port>"<<std::endl;exit(1);}sock=socket(PF_INET,SOCK_STREAM,0);if(sock==-1)error_handling("socket() error");memset(&serv_adr,0,sizeof(serv_adr));serv_adr.sin_family=AF_INET;serv_adr.sin_addr.s_addr=inet_addr(argv[1]);serv_adr.sin_port=htons(atoi(argv[2]));if(connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)error_handling("connect() error");elsestd::cout<<"connect ......"<<std::endl;std::cout<<"Operand count: ";std::cin>>opnd_cnt;//获取运算个数opmsg[0]=(char)opnd_cnt;for(i=0;i<opnd_cnt;i++){std::cout<<"Operand "<<i+1<<": ";std::cin>>*(int*)&opmsg[i*OPSZ+1];std::cin.ignore();//相当于换行}std::cout<<"Opreator: ";std::cin>>opmsg[opnd_cnt*OPSZ+1];//输入运算符write(sock,opmsg,opnd_cnt*OPSZ+2);//传输给服务器端read(sock,&result,RLT_SIZE);std::cout<<"Operation result: "<<result<<std::endl;close(sock);return 0;
}void error_handling(const char *message){std::cout<<message<<std::endl;exit(1);
}
相关文章:

day-03 基于TCP的服务器端/客户端
一.理解TCP和UDP TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)是两种常见的传输层协议,用于在计算机网络中提供可靠的数据传输。 1.TCP: 连接导向:TCP是一种面向连接的…...

匿名对象和一般对象的区别
1.格式的不同 一般对象的格式: Object obj new Object(); 匿名对象的格式: new Object(); 2.作为参数传递机制的不同 2.1先看看一般对象的使用机制 执行步骤: 1.首先程序进入main()函数,执行Object obj,…...

[MyBatis系列⑥]注解开发
🍃作者简介:准大三本科网络工程专业在读,持续学习Java,努力输出优质文章 ⭐MyBatis系列①:增删改查 ⭐MyBatis系列②:两种Dao开发方式 ⭐MyBatis系列③:动态SQL ⭐MyBatis系列④:核心…...

[ACL2023] Exploring Lottery Prompts for Pre-trained Language Models
Exploring Lottery Prompts for Pre-trained Language Models 文章链接 清深的工作,比较有意思的一篇。作者先给出假设,对于分类问题,在有限的语料空间内总能找到一个prompt让这个问题分类正确,作者称之为lottery prompt。为此&…...

【Python编程】将同一种图片分类到同一文件夹下,并且将其分类的路径信息写成txt文件进行保存
注:数据结构同上一篇博文类似 一、代码 import os import cv2 import shutilpath0os.getcwd()\\apple\\RGB path1os.getcwd()\\apple\\tof_confidence # path2os.getcwd()\\apple\\tof_depth # path3os.getcwd()\\apple\\tof_depthRGB # path4os.getcwd()\\apple\…...

单例模式的相关知识
饿汉模式 package Thread; class Singleton{private static Singleton instance new Singleton();public static Singleton getInstance(){return instance;}private Singleton(){} }public class demo1 {public static void main(String[] args) {Singleton S1 Singleton.ge…...

vue问题相关记录
1. vue的 nextTick的原理 首先vue实现响应式并不是数据发生变化后dom立即更新,而是按照一定的策略 异步执行dom更新的。 vue在修改数据后,试图不会立即进行更新,而是要等同一事件循环机制内所有数据变化完成之后,在统一更新 next…...

skywalking服务部署
一、前言 Apache SkyWalking 是一个开源的分布式跟踪、监控和诊断系统,旨在帮助用户监控和诊断分布式应用程序、微服务架构和云原生应用的性能和健康状况。它提供了可视化的分析工具,帮助开发人员和运维团队深入了解应用程序的性能、调用链和异常情况 …...

【uni-app】压缩图片并添加水印
总体思路 dom 结点 这里的 cvHeight 和 cvWidth 初始时要设置为你后续需要压缩后的最大宽高。假设我们在图片上传后图片最大为 350 * 350 <u-upload :fileList"baseInfoFormData.entrustFileList" afterRead"afterFileRead" multiple></u-uploa…...

《每天十分钟》-红宝书第4版-变量、作用域与内存
最近有点忙,好长时间没抄经了,今天继续,之前语言基础相对简单,跳过一部分操作符。 变量 js 的变量是特殊的松散类型,由于没有规则定义变量必须包含什么数据类型,变量的值和数据类型在脚本生命期内可以改变…...

NFTScan | 08.21~08.27 NFT 市场热点汇总
欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。周期:2023.08.21~ 2023.08.27 NFT Hot News 01/ NFT 品牌体验平台 Recur 将于 11 月 16 日彻底关闭,此前曾获 5000 万美元融资 8 月 21 日,NFT 品牌体验平台 Recur 在 X…...

【Java 中级】一文精通 Spring MVC - 数据验证(七)
👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区&#x…...

css奇数偶数选择器
前端项目开发中,需要根据行数的奇数和偶数的不同,设置不同的颜色显示,以在视觉上给用户以良好的浏览体验,这里就需要使用css奇数偶数选择器。 主要用的::nth-of-type或者:nth-child。 方式一:nth-child div:nth-chi…...

【算法】双指针求解盛最多水的容器
Problem: 11. 盛最多水的容器 文章目录 题目解析算法原理讲解复杂度Code 题目解析 首先我们来解析一下本题 题目中说到,要找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 那我们现在来看最外侧的两根,一个高度为8&#…...

浅析SAS协议:设备接入与探测
文章目录 SAS设备初始化OOB信号SAS设备间OOB交互场景一:SAS设备两边同时发送SAS COMINIT信号场景二:SAS设备A先发送COMINIT信号场景三:SAS设备B错过COMINIT信号 SAS与SATA设备间OOB交互场景一:SATA设备未响应COMSAS信号场景二&…...

RISC-V IOPMP实际用例-Andes SoC‘s Rapid-k模型
安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明:本文参考RISC-V 2023中国峰会如下议题,版权归原作者所有。...

【高阶数据结构】哈希表详解
文章目录 前言1. 哈希的概念2. 哈希冲突3. 哈希函数3.1 直接定址法3.2 除留余数法--(常用)3.3 平方取中法--(了解)3.4 折叠法--(了解)3.5 随机数法--(了解)3.6 数学分析法--(了解) 4. 哈希冲突的解决方法及不同方法对应的哈希表实现4.1 闭散列(开放定址法࿰…...

C#与西门子PLC1500的ModbusTcp服务器通信4--搭建ModbusTcp客户端
1、客户端选择 客户端可以是一个程序或一个设备,这里我以C#WINFORM程序来实现客户机与PLC的Modbustcp服务器通信,开发环境是VS2019,.NET Framework版本是4.7.2 2、创建winform程序 3、引入Nmodbus4协议 找到项目,找到引用&…...

性能调优篇 二、Jvm监控及诊断工具-命令行篇
目录 一、概述1、简单命令行工具 二、jps:查看正在运行的Java程序(掌握)1、是什么?2、测试3、基本语法 三、jstat:查看jvm统计信息(掌握)1、是什么?2、基本语法3、补充 四、jinfo&am…...

Fooocus启动时modules报错的解决方法
原理:是由于其他程序的安装导致modules的版本不对,先卸载现有版本,再运行run.bat让其自动安装响应的modules版本。 1、cmd运行windows dos终端。 2、将Fooocus_win64_1-1-1035文件夹备份,rename为Fooocus_win64_1-1-1035backup文…...

RSA私钥解密操作
RSA私钥解密操作 一、背景二、操作三、常见问题3.1 invalid key format3.2 解密的数据太长3.3 Decryption error 一、背景 项目数据库中存放的敏感字段已使用rsa加密的方式,将内容加密成密文存放, 现在需要在使用的时候,使用私钥进行解密。 二、操作 …...

数据库基本知识
基本概念 数据 描述事物的符号记录称为数据,数字,文字,图形,图像,声音,档案记录等都是数据 数据是以“记录”的形式按照统一的格式进行存储的,而不是杂乱无章的 相同格式和类型的数据统一存…...

使用Redis统计网站的UV/DAU
HyperLogLog/BitMap 统计UV、DAU需要用到Redis的高级数据类型 M public class RedisKeyUtil {private static final String PREFIX_UV "uv";private static final String PREFIX_DAU "dau";// a single days UVpublic static String getUVKey(String …...

【python】报错:ImportError: DLL load failed: 找不到指定的模块 的详细解决办法
原因:安装的包与python版本不一致 解决方法: 查看python版本: #python / #python -V Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] on win32只查看python第三方模块(库、包&…...

SemrushBot蜘蛛爬虫屏蔽方式
查看访问日志时候发现有SemrushBot爬虫 屏蔽方法: 使用robots.txt文件是一种标准的协议,用于告诉搜索引擎哪些页面可以和不能被爬取,如想禁止Googlebot爬取整个网站的话,可以在该文件中添加以下内容: User-agent: Googlebot Disallow: / 对于遵循robots协议的蜘蛛…...

6 ssh面密登录
1. 首先进入自己的家目录,执行命令 [atguiguhadoop102 .ssh]$ ssh-keygen -t rsa然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥) 2. 将公钥拷贝到要免密登录的…...

基于微信小程序的汽车租赁系统的设计与实现ljx7y
汽车租赁系统,主要包括管理员、用户二个权限角色,对于用户角色不同,所使用的功能模块相应不同。本文从管理员、用户的功能要求出发,汽车租赁系统系统中的功能模块主要是实现管理员后端;首页、个人中心、汽车品牌管理、…...

优化学习体验的在线考试系统
随着互联网的发展,在线教育逐渐成为学习的主要方式之一。在线考试系统作为在线教育的重要组成部分,对于学习者提供了更为便捷和灵活的学习方式。但是,如何优化学习体验,提高学习效果,仍然是在线考试系统需要解决的问题…...

1267. 统计参与通信的服务器
题目描述: 这里有一幅服务器分布图,服务器的位置标识在 m * n 的整数矩阵网格 grid 中,1 表示单元格上有服务器,0 表示没有。 如果两台服务器位于同一行或者同一列,我们就认为它们之间可以进行通信。 请你统计并返回能…...

【考研数学】矩阵、向量与线性方程组解的关系梳理与讨论
文章目录 引言一、回顾二、梳理齐次线性方程组非齐次线性方程组 写在最后 引言 两个原因让我想写这篇文章,一是做矩阵题目的时候就发现这三货经常绑在一起,让人想去探寻其中奥秘;另一就是今天学了向量组的秩,让我想起来了之前遗留…...