http

http

  • http创建 简易服务
  • http.get 发送get请求
    • let http = require('http')
    • let app = http.createServer(function(req,res){})
    • app.listen(80)})
let http = require('http')

//req 相当于是客户端的请求  可读流
//res 是代表响应的东西      可写流
http.createServer(function(req,res){
  // 设置请求头
  res.setHeader('Access-Control-Allow-Orign','*')
  console.log(req.method)
  //请求头 都是小写 content-type
  console.log(req.headers) // 是一个对象

  //怎么获取 传递过来的请求体
  //相当于取请求体 取数据  也就是 req是可读流   on('data')
  //没有请求体 不会触发data事件
  let arr = []
  req.on('data',function(data){
    arr.push(data)
      console.log('获取到的请求体',data)
  })
  req.on('end',function(data){
    console.log(Buffer.concat(arr).toString())
    // res.write('hello')
    // res.end(); //表示结束了
    res.statusCode = 200
    res.end('hello')// 他会先调用write写入 在调end返回
  })
}).listen(3000,'localhost',function(data){
  console.log('3000端口启动了')
})

requset

  • 创建一个客户端
let client = http.request({
  host:'localhost',
  method:'post',
  port:3000,
  path:'/user',
  headers:{
    name:'zfpx'
  }
},function(){

})
// 请求体
client.end('age=9')

url

- 格式:http://user:pass@wwww.example.jp:80/dir/index.html?uid=1#ch1 - http 协议,user:pass 登陆信息,wwww.example.jp 服务器地址,80 端口号,dir/index.html 文件路径,uid查询参数,ch1 hash发送的时候 后台拿不到

状态码

类别 原因短语
1XX Informational(信息性状态码)
2XX Success(成功状态码)
3XX Redirection(重定向)
4XX Client Error(客户端错误状态码)
5XX Server Error(服务器错误状态吗)

2xx 成功

  • 200(OK 客户端发过来的数据被正常处理
  • 204(Not Content 正常响应,没有实体
  • 206(Partial Content 范围请求,返回部分数据,响应报文中由Content-Range指定实体内容

3XX 重定向

  • 301(Moved Permanently) 永久重定向
  • 302(Found) 临时重定向,规范要求方法名不变,但是都会改变
  • 303(See Other) 和302类似,但必须用GET方法
  • 304(Not Modified) 状态未改变 配合(If-Match、If-Modified-Since、If-None_Match、If-Range、If-Unmodified-Since)
  • 307(Temporary Redirect) 临时重定向,不该改变请求方法

4XX 客户端错误

  • 400(Bad Request) 请求报文语法错误
  • 401 (unauthorized) 需要认证
  • 403(Forbidden) 服务器拒绝访问对应的资源
  • 404(Not Found) 服务器上无法找到资源

5XX 服务器端错误

  • 500(Internal Server Error)服务器故障
  • 503(Service Unavailable) 服务器处于超负载或正在停机维护

首部

tcp

  • 优化策略

滑动窗口

  • tcp 是全双工, 客户端和服务端 都有自己的缓存区域, 会根据网络调整发送数据的多少, 数据是乱序发送的,当接受到某个包,可能之前的包没有收到,此时需要等待前面序号的包到了才可以(队头堵塞)
  • 如果某个数据丢包了 那需要重新发送(超时重传 RTO)
  • 当接收方的缓存区满了 每隔一段时间 发送方会 会发送一个探索包 来询问能否调整窗口大小,同时上层协议消耗掉了接收方的数据,接收方也会主动通知发送方调整窗口 继续发送数据
  • 一帧 大 概1500 个字节: ip 20字节 tcp头 20字节 tcp剩下的 1460字节
  • 问题: 每次去咨询窗口大小 都会发送一次请求 比较浪费 性能差

粘包

  • nagle 算法 在同一时间内,最多只能有一个未被确认的小段 (TCP 内部控制) node 默认用它
    • 发送和确认的很快 nagle无法控制到
  • cork算法(粘包) 当达到最大值时统一进行发送(此时就是帧的大小 - ip头 - tcp头 = 1460个字节) 理论值

拥塞处理

  • 拥塞处理 快重传 快恢复(Reno算法)
    • 快重传: 可能在发送的过程中出现丢包现象,此时不要立即回退到慢阶段开始,而是对已接受到的报文进行重复确认,如果达到3次,则立即进行重复传, 快恢复算法(减少超时重传机制出现),降低cwnd的频率
    • 先从指数增长,达到一定的值,在线性增长
    • 恢复成原来的一半

http的一些问题

  • TCP顺序问题 后面的包先到达需要等待前面的包返回之后才可以继续传输(队头堵塞问题)
  • 慢启动的过程 非常消耗性能
  • time-wait 客户端链接服务器最后不会立即断开 在高并发 短链接的情况下啊 会出现端口全被占用

http/1.1 (纯文本协议,安全问题 明文 => https)

  • 基于tcp 传输层 半双工通讯(请求应答模式),http 默认是无状态(默认tcp 不能在没有应答完成后复用tcp 通道继续发送消息)
  • tcp的规范 就是固定的组成结构
    • 请求行 响应行 请求行 响应行 主要的目的就说是描述我要做什么事 服务端告诉客户端ok
    • 请求头 响应头 描述我们传输的数据内容 自定义我们的header (http中自己所做的规范)
    • 请求体 响应体 两者的数据

请求头和 响应头

  • 客户端 服务端

  • Accept Content-Type 数据类型

  • Accept-encoding Content-Encoding 发的数据是用什么格式压缩(gzip,deflate,br)

  • Accept-language 语言

  • Range Content-Range 范围请求数据

  • 核心在于内容协商

  • http 实现长链接 会默认在请求的时候 增加 connection:keep-alive, connection:close 复用tcp通道传递数据(必须在一次请求应答后才能复用) (队头阻塞 http1.1中的)

  • 多个请求

管线化方式传递数据

  • 我们针对每个域名 分配6 个 tcp 通道(域名分片 域名不宜过多,过多会导致dns解析大量域名)
  • 问题在与 虽然请求是并发的但是 应答依然是按顺序 (管道的特点就是先发送的先回来) (队头阻塞 http1.1中的)

可以采用cookie使用用户身份

协商缓存