HTTP协议

芝麻凛 2021年07月07日 145次浏览

HTTP知识总结

(HyperText Transfer Protocol 缩写HTTP)

李爵士发明的三样东西 WWW=URL + HTTP + HTML

先从IP说起:

什么是IP = Internet Protocol

主要约定了两件事

  1. 如何定位一台设备
  2. 如何封装数据报文,以及跟其他设备交流

只要你在互联网中,你就至少有一个独立的IP

IP分为内网和外网

image20210812195637199.png

如何获取外网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

那它们是什么关系

  • com是顶级域名
  • baidu.com是二级域名(俗称一级域名)
  • www.baidu.com 是三级域名(俗称二级域名)
  • 它们是父子关系
  • Github.io 把子域名 xxx.github.io 免费给你使用
  • 所以www.baidu.com 和 baidu.com 可以不是同一家公式
  • www是多余的。

如何请求不同的页面

路径可以做到

工具

  • 使用Chrome开发者工具 Network 面板看看区别

同一个页面,不同内容

查询参数可以做到

同一个内容,不同位置

锚点可以做到

注意

  • 锚点看起来有中文,实际不支持中文
  • #参考书会变成#%E5%8F之类的字符串
  • 锚点无法在Network面板看到
  • 因为锚点不会传给服务器

URL: 协议 + 域名或IP + 端口号 + 路径 + 查询字符串 + 锚点(统一资源定位符 Uniform Resource Locator 简称URL)

URL举例
image20210812212713853.png

HTTPS默认端口是443。

HTTP(协议)

它基于TCP和IP两个协议

CURL命令

用curl可以发HTTP请求

理解以下概念

  • url会被curl 工具重写,先请求DNS获得IP
  • 先进行TCP链接,TCP链接成功后,开始发送HTTP请求
  • 请求内容看一眼
  • 响应内容看一眼
  • 响应结束后,关闭TCP链接
  • 真正结束

HTTP

  • 规定的请求格式是,响应的格式是

HTTP 请求与响应

前置条件

  • 安装node.js 14+
  • 理解IP 和 端口
  • 理解URL 路径和 查询参数

请求与响应模型

image20210812223605202.png

来自饥人谷方方老师的灵魂绘画

如何发送请求

方法

  • 用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 构造请求

设置请求动词

  • -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 执行上一句命令

多账户示意图

image20210814133039612.png

安装 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