HTTP知识总结
(HyperText Transfer Protocol 缩写HTTP)
李爵士发明的三样东西 WWW=URL + HTTP + HTML
先从IP说起:
什么是IP = Internet Protocol
主要约定了两件事
- 如何定位一台设备
- 如何封装数据报文,以及跟其他设备交流
只要你在互联网中,你就至少有一个独立的IP
IP分为内网和外网
如何获取外网IP
- 从电信租用带宽,一年一千左右
- 买一个路由器,如何用电脑和手机分别连接路由器广播出来的无线WIFI
- 只要路由器连上电信的服务器,那么路由器就会有一个[外网IP],比如[14.17.32.211] 就是一个外网IP。这就是你再互联网中的地址
- 但是如果你重启路由器,那么你有可能被重新分配一个外网IP,也就是说你的路由器没有 固定的外网IP
- 如果你的路由器的外网IP是 14.17.32.211 ,那么你的手机和电脑IP又是什么呢?答案是 [内网IP]
内网IP
- 路由器会在你家里创建一个内网,内网中的设备使用内网IP,一般来说这个IP的格式都是192.168.xxx.xxx。
- 一般路由会给自己分配一个好记的内网IP,如 192.168.1.1
- 然后路由会给每一个内网中的设备分配一个不同的内网IP,如电脑是192.168.1.2,手机是192.16.8.1.3,以此类推
路由器的功能
- 现在路由器有两个IP,一个外网一个内网IP
- 内网中的设备可以互相访问,但是不能直接访问外网
- 内网设备想要访问外网,就必须经过路由器中转
- 外网中的设备想要把内容送到内网,也必须通过路由器
- 也就是说内网和外网就像两个隔绝的空间,无法互通,唯一的联通店就是路由器
- 所以路由器有时候也被叫做 [网关]
有几个特殊的IP
分别是
- 127..0.0.1 表示本机地址
- localhost 通过 hosts 指定为自己
- 0.0.0.0 不代表任何设备
IP有了还需要端口,一台机器可以提供很多服务,每个服务有一个号码,这个号码就是端口号port
端口port
- 要提供HTTP服务最好使用 80 端口
- 要提供 HTTPS 服务最好使用 443 端口
- 要提供FTP服务最好使用21端口
- 一共有 65535 个端口
端口使用有哪些规则
规则
- 0 到 1023(2的10次方-1)号端口是留给系统使用的
- 只有拥有了管理员权限后,才能使用者1024个端口
- 其他端口可以给普通用户使用
- 比如http-server 默认使用8080端口
- 一个端口如果被占用,就只能再换一个端口使用了
IP和端口缺一不可。
域名是什么
域名就是对IP的别称
- 通过 ping baidu.com 可以查看百度对应什么IP
- 一个域名可以对应不同的IP
- 这个叫做负载均衡,防止一台机器扛不住
- 一个ip可以对应不同域名
- 这个叫做共享主机
域名和IP通过DNS对应起来。DNS域名系统(英语:Domain Name System,缩写:DNS),nslookup github.io可以查看github对应的IP。
当你输入baidu.com
过程
- 你的Chrome浏览器会向电信/联通 提供的DNS服务器询问 baidu.com 对应什么IP
- 这时电信/联动 会回答一个ip(具体过程很复杂,暂不研究)
- 然后Chrome才会向对应IP的 80/ 443端口发送请求
- 请求内容是查看baidu.com 的首页
为什么是80 或 443端口
- 服务器默认用80提供http服务
- 服务器默认用443提供https服务
- 可以在开发者工具里看到具体的端口
www
- www.baidu.com 和 baidu.com 不是同一个域名
那它们是什么关系
- com是顶级域名
- baidu.com是二级域名(俗称一级域名)
- www.baidu.com 是三级域名(俗称二级域名)
- 它们是父子关系
- Github.io 把子域名 xxx.github.io 免费给你使用
- 所以www.baidu.com 和 baidu.com 可以不是同一家公式
- www是多余的。
如何请求不同的页面
路径可以做到
工具
- 使用Chrome开发者工具 Network 面板看看区别
同一个页面,不同内容
查询参数可以做到
同一个内容,不同位置
锚点可以做到
- https://developer.mozilla.org/zh-CN/docs/Web/CSS#参考书
- https://developer.mozilla.org/zh-CN/docs/Web/CSS#教程
注意
- 锚点看起来有中文,实际不支持中文
- #参考书会变成#%E5%8F之类的字符串
- 锚点无法在Network面板看到
- 因为锚点不会传给服务器
URL: 协议 + 域名或IP + 端口号 + 路径 + 查询字符串 + 锚点(统一资源定位符 Uniform Resource Locator 简称URL)
URL举例
HTTPS默认端口是443。
HTTP(协议)
它基于TCP和IP两个协议
CURL命令
用curl可以发HTTP请求
- curl -v http://baidu.com
- curl -s -v --https://ww.baidu.com
理解以下概念
- url会被curl 工具重写,先请求DNS获得IP
- 先进行TCP链接,TCP链接成功后,开始发送HTTP请求
- 请求内容看一眼
- 响应内容看一眼
- 响应结束后,关闭TCP链接
- 真正结束
HTTP
- 规定的请求格式是,响应的格式是
HTTP 请求与响应
前置条件
- 安装node.js 14+
- 理解IP 和 端口
- 理解URL 路径和 查询参数
请求与响应模型
来自饥人谷方方老师的灵魂绘画
如何发送请求
方法
- 用Chrome 地址栏输入URL
- 使用CURL命令
概念
- 帮助我们发送请求的工具叫做[用户代理](User Agent)
如何做出一个响应
需用编程
- Node.js有一个http模块可以做到
- 初始代码如下直接用
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)
if(path === '/'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`二哈`)
response.end()
} else if(path === '/x'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/css;charset=utf-8')
response.write(`body{color: red;}`)
response.end()
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
})
server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)
将以上代码保存为server.js 命令行运行:node server.js 8888
注意事项
- 这些代码就是服务器代码,一般放在服务器上
- path是不带查询参数的路径 /x
- query 是查询参数的对象行使{a:'1'}
- queryString是查询参数的字符串形式 ?a=1
- pathWithQuery 是带查询参数的路径,一般不用
- request 是请求对象
- response 是响应对象
代码逻辑
语法
这种字符串
里面可以回车- ‘这种字符串’ 里面要回车只能用 \n 表示
逻辑
- 每次收到请求都会把中间的代码执行一遍
- 用 if else 判断路径,并返回响应
- 如果是已知路径,一律返回 200
- 如果是未知路径,一律返回 404
- Content-Type 表示内容的 [类型/语法]
- response.write() 可以填写返回的内容
- response.end() 表示响应可以发送给用户了
关于上面的代码
- 写了一个服务器程序
- 然后我们在./路径返回一个HTML内容
- 在/x 路径返回一个CSS内容
- 在/y 路径返回一个JS内容,通过标签( path=== "x")把他们连接起来,这样我们就写了一个页面了
注意事项
- URL 里面的后缀不一定有用,/y.css 不一定是css内容
- Content-Type 才是决定文件类型的关键
HTTP基础概念
请求
- 请求动词 路径加查询参数 协议名/版本
- Host:域名或IP
- Accept:text/html
- Content-Type:请求体的格式
- 回车
- 请求体(也就是上传内容)
细节
- 三部分:请求行、请求体、请求体
- 请求动词有GET/POST/PUT/PATCH/DELETE等
- 请求体在GET请求中一般为空
- 文档位于 RTC2616 第五章
- 大小写不敏感。
响应
- 协议名/版本 状态码 状态字符串
- Content-Type:响应体的格式
- 回车
- 响应体(也就是下载内容)
细节
- 三部分: 状态行、响应头、响应体
- 常见的状态码是考点
- 文档位于 RFC 2616 第六章
必须学会什么
- 基础概念(有哪些是必会的)
- 如何调试(用的是Node.js,可以用log/ debugger)
- 在哪查资料(用的是Node.js,看Node.js文档)
- 标准的制定者是谁(HTTP规范文档:RFC2616等)
如何学
- CRM --- 抄文档,运行,加入自己的想法,再次运行。
用CURL 构造请求
- curl -v http://127.0.0.1:8888
设置请求动词
- -X POST
- 注意大小写
设置路径和查询参数
- 直接在url后面加
设置请求头
- -H 'Name: Value' 或者 --header 'Name:Value'
设置请求体
- -d '内容' 或者 --data '内容'
curl -v -X POST -H 'Rick: Good' -H 'Content-Type: text/plain;charset=utf-8' -d '请求体内容' http://localhost:8888/xxxxxx?wd=hi#nihao
用Node.js 读取请求
读取请求动词
- request.method
读取路径
- request.url 路径,带参数查询
- path 纯路径,不带查询参数
- query 只有查询参数
读取请求头
- request.headers['Accept']
读取请求体
用Node.js 设置响应
设置响应状态码
- response.statusCode = 200
设置响应头
- response.setHeader('Content-Type','text/html');
设置响应体
- response.write('内容')
- 可追加内容
SSH远程登录
步骤
- 首先登录root账户
- 成功后看到Welcome之后
- echo '复制本地~/.ssh/id_rsa.pub内容' >> ~/.ssh/authorized_keys
- 新建终端,在本地运行 ssh root@实例ip
- 然后就可以在本地终端操作云服务器了
echo '复制本地~/.ssh/id_rsa.pub内容' >> ~/.ssh/authorized_keys
刚才做了什么
- 把本地的公钥复制到阿里云的 ~/.ssh/authorized_keys
- 在本地用 ssh root@实例ip 来远程操作云机器
- 以后都用 ssh root@实例ip 的方式即可
- 你可以在 hosts 里给实例ip 取个别名
- 想要退出云机器,可以输入 exit 回车
- 如果卡了,可以直接退出终端 ctrl + W
防止 ssh 卡住
echo "Host *" >> /etc/ssh/ssh_config
echo " ServerAliveInterval 30" >> /etc/ssh/ssh_config
- 在 /etc/ssh/ssh_config 最后加下面两句话
- Host * ServerAliveInterval 30
- 用 code 打开这个文件应该会失败
- 可以用两次 echo 搞定
- echo "Host *" >> /etc/ssh/ssh_config
- echo " ServerAliveInterval 30" >> /etc/ssh/ssh_config
- 不要少写了空格
- 重启终端生效,如果没生效就重启机器
创建应用账户
adduser rick
mkdir /home/rick/.ssh
cp ~/.ssh/authorized_keys /home/rick/.ssh/
chmod 755 /home/rick/.ssh/authorized_keys
chown rick:rick /home/rick/.ssh/authorized_keys
adduser rick sudo #给 frank 添加 sudo 权限
Linux 的 root 账户拥有最高权限,一旦被攻克……
步骤
- adduser rick
- Enter new UNIX password: 输入密码
- 再次输入密码,密码可以跟 root 的密码一样
- 一直回车,直到结束,运行如下命令
- mkdir /home/rick/.ssh
- cp ~/.ssh/authorized_keys /home/rick/.ssh/
- chmod 755 /home/rick/.ssh/authorized_keys
- chown rick:rick /home/rick/.ssh/authorized_keys
- 现在 ssh rick@实例ip 就可以使用了
- sudo 是什么
- 全称 super user do
- 类似于 Windows 的「以管理员身份运行」
- 平时你不应该使用 root 账户,而是用 frank 账户
- 遇到特殊操作,就在前面加 sudo,请出 root
- 需要输入 frank 的密码,不是 root 的密码
- 使用 ctrl + A 可以快速回到命令前面
- sudo !! 的意思是用 sudo 执行上一句命令
多账户示意图
安装 Node.js 14
curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -
sudo apt-get update
sudo apt-get install -y nodejs
node -v
npm -v
npx -v
sudo apt install git
如果你已经装了8,想要换成14怎么办?
sudo apt-get remove nodejs
找到 /etc/apt/sources.list.d/nodesource.list 文件,把它的内容全删掉并保存
然后重新执行上方的安装脚本
安装git
- sudo apt install git
- 遇到 [Y/n] 输入回车,或者 y 回车
- git --version
- 注意
- 由于无界面环境,安装不了 VSCode,vim 又太难
- 所以不要使用 git commit -v 改用 -m "xxx"
- 如果想学习 vim,在本地电脑输入 vimtutor 看完
- 新人不要浪费时间学习 vim
- 实在不行,就去阿里云页面重启机器即可
部署应用
git clone https://github.com/rick/nodejs-test.git
cd nodejs-test
touch log
启动命令:node server.js 8888 > log 2>&1 &
把启动命令做成 start 文件
添加执行权限 chmod +x ./start
运行 sh ./start 得到一个进程号 pid
tail log 看 log 内容
kill -9 pid 可以关掉进程
killall node 可以关掉所有 node 进程
如何重启应用
ssh rick@实例ip
cd nodejs-test
git pull
killall node(因为忘了进程号,实际上可以记下来)
sh ./start