[ 网络 ] 应用层协议 —— HTTP协议
目录
1.HTTP协议
1.1URL
urlencode和urldecode
2. HTTP协议格式
HTTP请求
HTTP响应
3.告知服务器意图的HTTP方法
GET:获取资源
POST:传输实体主体
GET和POST的区别
使用Cookie的状态管理
4.返回结果的HTTP状态码
状态码告知从服务器端返回的请求结果
2XX成功
3XX重定向
4XX客户端错误
5XX服务器错误
5.HTTP的缺点
1.HTTP协议
应用层协议已经有大佬定义了一些现成的,有非常好用的应用层协议,我们可以直接参考使用。例如本篇所提到的HTTP(超文本传输协议)就是其中之一。
1.1URL
URL(统一资源定位符)就是我们俗称的"网址"
我们所常见到的网址:例如 https://www.baidu.com/ 是域名,这种字符串风格的域名,具有更好的字描述性。域名在解析时必须被转换成为IP地址,要访问网络服务,又必须具有port.
协议方案名和服务器端口号是强绑定的:
比如httpserver --- 80 ; httpsServer --- 443 ; sshd --- 22
HTTP协议的本质是要获得某种"资源",比如我们请求百度的官网时,我们所获取的资源是百度首页的网页信息。我们可以理解为HTTP是 获取网页资源的(视频,音乐等)。HTTP是向特定的服务器向特定端口申请特定的"资源"的,获取到本地进行展示或者某种展示的。而对应服务器上,你所要的资源所在的位置就是URL中带层次的文件路径。
实际上,上网的大部分行为,都在进行这进程间通信。既然是通信,就是获取信息和发送信息。所以我们对应到生活中,大部分的上网行为,无非两种:
- 把服务器上面的资源数据拿到本地(短视频,小说等等)
- 把本都的数据推送到服务器(搜索,注册,登录,下单等)
urlencode和urldecode
在URL中,像 / ? 等这样的字符已经被URL当做特殊意义理解了。因此这些字符不能随意出现。
比如:某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义。
转义规则:将需要转码的字符转为16进制,然后从右到做,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。
我们可以看到 "C++" 中 "+"被转义成了 "%2B" 我们可以使用urlencode工具验证上述过程
UrlEncode编码/UrlDecode解码 | urldecode就是urlencode的逆过程。
2. HTTP协议格式
HTTP请求
- 首行:【方法】+【URL】+【版本】
- Header:请求的属性,冒号分割的键值对;每组属性之间使用\n分割;遇到空行表示Header部分结束
- Body:空行后面的内容都是Body.Body允许为空字符串.如果Body存在,则在Header中会有一个Content-Length字段用来表示Body的长度
常规情况下,HTTP(HTTPS)底层使用的传输层协议是TCP.
我们通过一段tcp套接字编程来查看HTTP请求格式
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>using namespace std;
int main()
{int listen_sock = socket(AF_INET,SOCK_STREAM,0);if(listen_sock < 0){std::cout<<"socket error" <<std::endl;return 1;}struct sockaddr_in local;memset(&local,0,sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(8082);local.sin_addr.s_addr = INADDR_ANY;if(bind(listen_sock,(struct sockaddr*)&local, sizeof(local))<0){std::cout<<"bind error" << std::endl;return 2;}if(listen(listen_sock,5) < 0){std::cout<<"listen error" << std::endl;return 3;}struct sockaddr_in peer;for(;;){socklen_t len = sizeof(peer);int sock = accept(listen_sock,(struct sockaddr*)&peer,&len);if(sock < 0){std::cout<<"accept error "<<std::endl;continue;}if(fork() == 0){if(fork() > 0) exit(0);close(listen_sock);char buffer[1024];recv(sock,buffer,sizeof(buffer),0);std::cout<<"###################HTTP request begin####################"<<std::endl;std::cout<< buffer << std::endl;std::cout<<"###################HTTP request end####################"<<std::endl;exit(0);}close(sock);waitpid(-1,nullptr,0);}
}
我们在直接打印出请求的格式
第一部分 首行:请求方法 请求url HTTP协议的版本
常用的请求方法:GET和POST (后面详解)
刚刚我们请求的是 / . " / " 是Web根目录不是系统根目录。那我们也可以请求 /a/b/c/d.html 我们再次看看请求报文:
第二部分是一组Key:value的请求报头
请求报头是一堆Key: Value 请求属性,包括是否需要长链接,浏览器的编码类型,数据类型,我们想发送给服务器的相关信息等等.....通常存在多行,是一堆的Key: Value值
服务器端可以按行循环读取,一直读到\n (空行)就证明已经把报头读完了
第三部分:空行
是报头和有效载荷的分离符,为了就是将报头和有效载荷进行分离
前三部分都必须是按行方式陈列的
第四部分:请求正文(有效载荷) ——非必须 | 可以没有
根据我们的需求,有时候我们需要登录账号和密码,个人信息,音乐,视频等等一般都是用户的相关信息或者数据。
以上就是HTTP协议的请求(HTTP request)。
HTTP响应
- 首行: 【版本号】 + 【状态码】 + 【状态码解释】
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
- Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中.
HTTP响应也是由4部分组成,其中响应正文也是可以被省略的。客户端如何判断已经将response报头读取完毕呢,仍然是客户端可以循环按行读取,知道读取到空行。
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <fstream>using namespace std;
int main()
{int listen_sock = socket(AF_INET,SOCK_STREAM,0);if(listen_sock < 0){std::cout<<"socket error" <<std::endl;return 1;}struct sockaddr_in local;memset(&local,0,sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(8083);local.sin_addr.s_addr = INADDR_ANY;if(bind(listen_sock,(struct sockaddr*)&local, sizeof(local))<0){std::cout<<"bind error" << std::endl;return 2;}if(listen(listen_sock,5) < 0){std::cout<<"listen error" << std::endl;return 3;}struct sockaddr_in peer;for(;;){socklen_t len = sizeof(peer);int sock = accept(listen_sock,(struct sockaddr*)&peer,&len);if(sock < 0){std::cout<<"accept error "<<std::endl;continue;}if(fork() == 0){if(fork() > 0) exit(0);close(listen_sock);char buffer[1024];recv(sock,buffer,sizeof(buffer),0);// std::cout<<"###################HTTP request begin####################"<<std::endl;// std::cout<< buffer << std::endl;// std::cout<<"###################HTTP request end####################"<<std::endl;#define PAGE "./wwwroot/index.html"std::ifstream in(PAGE);if(in.is_open()){in.seekg(0,std::ios::end);size_t len = in.tellg();in.seekg(0,std::ios::beg);char *file = new char[len];in.read(file,len);in.close();std::string status_line = "http/1.0 200 OK\n";std::string response_header = "Content-Length: "+std::to_string(len);response_header+="\n";std::string blank = "\n";send(sock,status_line.c_str(),status_line.size(),0);send(sock,response_header.c_str(),response_header.size(),0);send(sock,blank.c_str(),blank.size(),0);send(sock,file,len,0);delete[] file;}close(sock);exit(0);}close(sock);waitpid(-1,nullptr,0);}
}
3.告知服务器意图的HTTP方法
在众多的HTTP方法中最常用的是GET和POST方法,因此在此我们对GET和POST进行详细了解
GET:获取资源
GET方法是用来请求访问已被URL识别的资源。指定的资源经服务器端解析后返回响应内容。
我们也可以使用Postman工具抓取HTTP请求
POST:传输实体主体
POST方法是用来传输实体的主体
虽然用GET方法也可以传输实体的主体,但是一般不用GET方法进行传输,而是用POST方法。虽然POST的功能和GET很相似,但是POST的主要目的并不是获取响应的主体内容。
GET和POST的区别
- GET方法可以带参,参数在URL " ?"的后面
- POST方法通过正文传参
- GET方法传参不私密
- POST方法因为通过正文传参,所以相对私密一些
GET通过url传参,POST通过正文传参,所以一般一些大的内容都是通过POST传参。
使用Cookie的状态管理
HTTP是无状态协议,它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求管理。那么我们在日常上网的过程中,假设要求登录认证的Web页面本身无法进行状态的管理(不记录已登录的状态),那么每次跳转新页面的时候都要再次登录,或者每次请求报文中附加参数来管理登录状态。那么这对我们用户是非常不友好的,就相当于我们每次登录C站我们都要进行登录认证。因此Cookie技术就是通过在请求和响应报文中写入Cookie信息来控制客户端的状态。
Cookie会根据从服务器端发送的响应报文内的一个叫Set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端再往服务器发送请求时,客户端会自动在请求报文中加入Cookie值后发送出去。服务器端发现过来的Cookie后,会检查究竟是从哪一个客户端的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。
举例:我们用B站来进行举例。
我只要登录过B站之后,再之后再次登录B站时会自动登录我的账号, 点击网址左边的锁,就会看到Cookie,点进去就会看到当前页面下的Cookie信息,我们全部进行删除后点击完成,再次刷新该页面,就发现无法找到之前的登录信息了。登录后再次查询发现Cookie信息被重新填写上了。
4.返回结果的HTTP状态码
HTTP状态码负责表示客户端HTTP请求的返回结果,标记服务器端的处理是否正常,通知出现的错误等工作。
状态码告知从服务器端返回的请求结果
状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求还是出现了错误。
状态码的类别
2XX成功
2XX的响应结果表明请求被正常处理了。
例如:
- 200 OK表示从客户端发来的请求在服务器端被正常处理了。
- 204 No Content 表示服务器接受的请求已成功处理,但在返回的响应报文中不含有实体的主体部分,也就是说请求处理成功但是没有资源可以返回。因此返回204响应后浏览器的显示页面不会发生更新。
3XX重定向
- 301 Moved Permanently 永久重定向。该状态码表示请求的资源已被分配了新的URL,以后应使用现在所指的URL。
- 302 Found 临时重定向。该状态码表示请求的资源已被分配了新的URL,希望用户本次能使用新的URL访问。
- 302和301状态码相似,但是302状态码代表的资源不是永久移动,只是临时性质的。换句话说,302的资源对应的URL将来还有可能发生变。
if(fork() == 0){if(fork() > 0) exit(0);close(listen_sock);char buffer[1024];recv(sock,buffer,sizeof(buffer),0);//重定向到腾讯网std::string response = "HTTP/1.1 301 Permanently Moved\r\n";response += "Location: https://www.qq.com/\r\n"; response += "\r\n";send(sock, response.c_str(), response.size(), 0);close(sock);exit(0);}
当服务器启动之后在浏览器输入ip:port后按下回车发现URL自动跳转到了腾讯网
4XX客户端错误
- 403 Forbidden 表示请求资源的访问被服务器拒绝了。服务器端没有必要给出拒绝的详细理由。
- 发生403的原因:未获得文件系统的访问授权,访问权限出现某些问题(从未授权的发送源IP地址试图访问)
- 404 Not Found 表示服务器上无法找到请求的资源。除此之外,也可能在服务器端拒绝请求且不想说明理由时使用。
5XX服务器错误
5XX的响应结果表名服务器本身发生错误
- 500 Internal Server Error 表示服务器端在执行请求时发生了错误。也可能是Web应用存在的Bug或某些临时的故障。
5.HTTP的缺点
HTTP主要有如下不足之处:
- 通信使用明文(不加密),内容可能会被窃听
- 不验证通信方的身份,因此有可能遭遇伪装
- 无法证明报文的完整性,所以有可能已经遭到篡改
因此解决如上三个不足之处正是HTTPS的主要功能,因此HTTPS = HTTP+加密+认证+完整性保护。具体3个功能的实现细节,将单独整理成一篇博客HTTPS
相关文章:
[ 网络 ] 应用层协议 —— HTTP协议
目录 1.HTTP协议 1.1URL urlencode和urldecode 2. HTTP协议格式 HTTP请求 HTTP响应 3.告知服务器意图的HTTP方法 GET:获取资源 POST:传输实体主体 GET和POST的区别 使用Cookie的状态管理 4.返回结果的HTTP状态码 状态码告知从服务器端返回的…...
Spring Boot 整合 Redisson 缓存性能客户端(2023-03-06)
Spring Boot 整合 Redisson 缓存 (官网) 介绍: Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, Sorte…...
【C和C++】输出100内能够被13整除的数,取模判断方法
目录 前言基础概念重温整除例子小知识点收尾前言 在软件行业已经有快十年,技术虽然一般般,但是足够应付和解决编程入门的相关问题! 都说十年磨一剑,积累到一定经验,是时候发挥自己的价值,给予入门的同行些许的帮助! 为什么要写收费专栏,其实原因很简单,时间就是金钱(…...
STC8单片机基于开源库读取DS18B20数据例程
STC8单片机基于开源库读取DS18B20数据例程 📍开源库FwLib_STC8 Github地址:https://github.com/IOsetting/FwLib_STC8📌STC官方STC8库函数资源:https://www.stcai.com/khs🎉本次利用FwLib_STC8库读取DS18B20,由于该开源库是基于VSCode编写,默认使用的是SDCC编译器,在…...
计算机专业毕业设计基于Spring Boot 学生在线考试系统
目录 一、学生端 1.1 登录 1.2 注册 1.3 学生首页 1.4 学生查看任务中心的试卷(已答卷/未答卷) 1.5 学生查看固定试卷以及开始做题 1.6 学生查看时段试卷以及开始做题 1.7 学生查看试卷中心 1.8 学生查看考试记录以及查看试卷 1.9 学生查看…...
【读书笔记】《深入浅出数据分析》第八章 启发法
目录一,什么是启发法?1,那什么是启发法?2,心理学上对启发法定义二,活动分析1,如何去分析活动效果呢?1.1 活动前期(活动前1-2周)1.2 活动中期1.3 活动结束一&a…...
英飞凌Tricore实战系列导读
本文框架 1.系列概述1.1 外设理论及应用介绍1.2 基于TC3xx的MCAL各外设配置开发1.3 基于TC3xx的Davinci工程开发1.4 项目中问题排查经验分享1.5 其他相关话题分享2. 目前已发布系列文章汇总1.系列概述 英飞凌TC3xx以其强大的性能,扩展性,存储及安全性能在汽车电子中扮演着越…...
做数据分析有前景吗?
当然有前景的。 每个行业都有发展前景,只是看你自身的技能情况或者关系人脉、软实力方面是否到位,不同的行业要求不一样。作为数据分析领域而言,属于IT行业,看的是你的专业技能;只要你技能过硬,就能在行业…...
Rust Web入门(六):服务器端web应用
本教程笔记来自 杨旭老师的 rust web 全栈教程,链接如下: https://www.bilibili.com/video/BV1RP4y1G7KF?p1&vd_source8595fbbf160cc11a0cc07cadacf22951 学习 Rust Web 需要学习 rust 的前置知识可以学习杨旭老师的另一门教程 https://www.bili…...
1.特定领域知识图谱知识融合方案(实体对齐):金融产业产业知识图谱-基于内容匹配和图模型的品牌知识链指
1 引言 供应链金融是一种围绕经营关系,以核心企业为依托,针对中小企业的新型金融服务。如何精准地还原企业间的经营关系,是供应链金融的关键所在。知识图谱是描绘实体间关系的网络结构,对于挖掘企业关系有重要意义。在真实场景中,仅有企业与用户的微观知识对于还原经营关系…...
前端基础语法合集
JS语法基础1-注释//单行注释/*......*/多行注释2-分号;用作分割javascript语句,可以省略。3-变量定义定义变量使用varvar a;//声明变量 var a100;//声明变量并赋值 var b,c;//声明多个变量 var d20;bd1;cb1;//一行多条语句要用;分割4-数据类型判断该变量…...
百亿补贴,京东的自卫反击战
“百亿补贴”这个词大家有没有很熟悉?大部分人应该是在看拼多多投放广告的时候,知道这个词的吧。而京东APP也于近日在升级11.6.2版本时,在更新日志中明确提到:“京东3.8节,百亿补贴上线”。至此,发酵数日的…...
融云入选中国信通院《高质量数字化转型产品及服务全景图》
企业数字化转型正在进入“深水区”。 3 月 3 日,“中国信息通信研究院(以下简称中国信通院)高质量数字化转型创新发展大会暨中国信通院‘铸基计划’年度峰会”在京召开,深度展示了中国信通院在数字化转型领域的工作成果ÿ…...
开源消息代理组件mosquitto
# ll total 556 -rw-r----- 1 sk sk 148417 Mar 6 14:59 libuv-1.44.2-1.el7.x86_64.rpm -rw-r----- 1 sk sk 120717 Mar 6 14:59 libwebsockets-3.0.1-2.el7.x86_64.rpm -rw-r----- 1 sk sk 293429 Mar 6 14:59 mosquitto-1.6.10-1.el7.x86_64.rpm 将用到的依赖上传到主机…...
vuex的五个属性及使用方法示例
一,Vuex简介 Vuex是Vue.js的状态管理库,它通过中心化的状态管理使得组件间的数据共享更加容易。 Vuex包含五个核心属性:state、getters、mutations、actions和modules。 Vuex是Vue.js的状态管理库,它提供了一种集中式存储管理应…...
9.SpringSecurity核心过滤器-SecurityContextPersistenceFilter
SpringSecurity核心过滤器-SecurityContextPersistenceFilter 一、SpringSecurity中的核心组件 在SpringSecurity中的jar分为4个,作用分别为 jar作用spring-security-coreSpringSecurity的核心jar包,认证和授权的核心代码都在这里面spring-security-co…...
23种设计模式-桥接模式
概念 桥接模式是一种结构型设计模式,它通过将抽象与其实现分离来解耦。它使用接口(抽象类)作为桥梁,将一个抽象类与其实现类的代码分别独立开来,从而使它们可以各自独立地变化。桥接模式的核心思想是“组合优于继承”…...
TCP PMTU 静态路由
HTTP协议 --- 超文本传输协议TCP --- 80端口超文本 --- 包含有超链接link和多媒体元素标记的文本TCP协议是一种面向连接的可靠性传输协议面向连接:数据在传输前,收发双方建立一条逻辑通道。可靠性确认机制:传输确认,每接受一个数据…...
Android动画——属性动画
在属性动画中,常用到的API有ValueAnimator,ObjectAnimator。ValueAnimator:时间引擎,负责计算各个帧的属性值,基本上其他属性动画都会直接或间接继承它;ObjectAnimator: ValueAnimator 的子类&a…...
华为OD机试真题Python实现【寻找连续区间】真题+解题思路+代码(20222023)
寻找连续区间 题目 给定一个含有N个正整数的数组, 求出有多少个连续区间(包括单个正整数), 它们的和大于等于x。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 ## 输入 第一行两个整数N x (0 < N <= 100000 ,0 <= x <=…...
15. 三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的三元组。 示例 …...
40-Golang中的文件
Golang中的文件基本介绍文件的打开和关闭读文件操作应用实例写文件操作实例判断文件是否存在基本介绍 文件在程序中是以流的形式存在的 流:数据在数据源(文件)和程序(内存)之间经历的路程 输入流:数据从数据源到程序之间的路径 输出流:数据…...
Springboot整合RabbitMQ并使用
1、Springboot整合RabbitMQ 1、引入场景启动器 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>引入AMQP场景启动器之后,RabbitAutoConfiguratio…...
Java中方法引用(引用静态方法、引用成员方法(引用其他类的成员方法、引用本类的成员方法、引用父类的成员方法)、引用构造方法、其他调用方式、小练习)
方法引用:把已经存在的方法拿过来用,当作函数式接口中抽象方法的方法体 我们前面学到Arrays工具类中的sort方法,当我们需要指定排序规则时,需要传递Comparator接口的实现类对象,我们之前使用匿名内部类类的形式作为参…...
整理了100道关于Python基础知识的练习题,记得收藏~
实例1.数字组合 题目: 有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析: 遍历全部可能,把有重复的剃掉。 total0 for i in range(1,5):for j in range(…...
OSG三维渲染引擎编程学习之七十七:“第七章:OSG场景图形交互” 之 “7.8 场景交互”
目录 第七章 OSG场景图形交互 7.8 场景交互 7.8.1 osgGA库 7.8.2 事件消息处理 7.8.3 程序抓图示例...
797.差分
输入一个长度为 n的整数序列。 接下来输入 m个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两个整数 n和 m。 第二行包含 n个整数,表示整数序列。 …...
为什么说要慎用BeanUtils,因为性能真的拉跨
1 背景之前在专栏中讲过“不推荐使用属性拷贝工具”,推荐直接定义转换类和方法使用 IDEA 插件自动填充 get / set 函数。不推荐的主要理由是:有些属性拷贝工具性能有点差有些属性拷贝工具有“BUG”使用属性拷贝工具容易存在一些隐患(后面例子…...
【项目设计】高并发内存池(六)[细节优化+测试]
🎇C学习历程:入门 博客主页:一起去看日落吗持续分享博主的C学习历程博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话: 也许你现在做的事情,暂时看不到成果,但不要忘记&…...
同模块设置不同应用主题方案
有时候公司内部会有不同应用但是有部分模块功能一样,只根据应用角色有些细节逻辑区分的场景。这时候往往采用模块化采用以应用至不同的APP。如果APP主题不一致,该如果解决。 方案: 在不同应用的config.gradle 下面根据不同应用定义不同的a…...
什么网站做任务赚钱/制作网站需要什么软件
一、测试数据:手机上网日志1.1 日志假设我们如下一个日志文件,这个文件的内容是来自某个电信运营商的手机上网日志,文件的内容已经经过了优化,格式比较规整,便于学习研究。每一行不同的字段又有不同的含义,…...
wordpress帮助手册/常用的搜索引擎有哪些?
前言 本文主要记录下关于斯坦福CS231n课程Lecture1——Lecture5中学习的笔记,以下部分内容为个人理解如有错误,敬请原谅。 一、传统机器学习和深度学习联系 不管是传统的机器学习还是深度学习,贯穿主线的就是特征,只不过传统的机…...
jsp网站开发实训报告/百度竞价推广的技巧
Collection 子接口: ArrayList是List 接口和Collection接口的一个子类,用于实例化两种接口 package leiji; import java.util.ArrayList; import java.util.List; import java.util.Collection; public class ArryList { public static void main(String…...
要加强县门户网站的建设管理办法/黑帽seo排名技术
程序员在为某个应用系统编写接入其它应用系统的程序代码的时候,常常为了用户认证大伤脑筋:1) 让最终用户频繁登录? 似乎是一个让用户很难接受的解决方案。2) 在代码中内置用户名和密码? 代码需要随用户和密码的变化经常维护,同时在很多场合…...
永年做网站多少钱/百度搜索引擎
题目 长度为n(n<1e5)的仅由abc三种字母组成的串, q(q<1e5)次操作,每次给出两个参数pos x(x属于a、b、c三种字母中的一种), 表示把pos位置的字母改成x, 每次改完之后,都需要输出把整个…...
网站百度收录秒收方法/手机免费建网站
看到有面试题里会有问到如何用css画出三角形 众所周知好多图形都可以拆分成三角形,所以说会了画三角形就可以画出很多有意思的形状 画出三角形的原理是调整border(边框)的四个方向的宽度,线条样式以及颜色。 如果你将宽度调的足够…...