6. 网络

OSI 七层模型(是理想化网络模型)

  1. 应用层
  2. 表示层
  3. 会话层 实际中 5.6.7 归成应用层
  4. 传输层 TCP UDP 协议
  5. 网络层 路由器
  6. 数据链路层 交换机 网卡
  7. 物理层 物理设备 网线 光纤

实际五层

  • 实际应用中会将会话层、表示层、应用层合并在一起为应用层
  1. 用户要传递的数据 装包 HTTP DNS
  2. 传输层 用户要传递很大的数据包 会对大的数据包进行拆分并标明序号 端口号用于传输到哪 TCP、UDP
  3. 网络层 对数据再次进行包装 ip 地址 如果传输层的数据还是非常大 网络层会再次进行分包 IP 协议
  4. 数据链路层 再次包装成
  5. 物理层 这两层涉及到的是硬件

五层模型(统称为 TCP/IP 协议 协议簇)

  • 能称为协议的都在数据链路层之上,所以在网络层、传输层、应用层才有协议
  • 协议的功能就是把数据按照某个规范去封装,再把数据进行传输(协议就是对数据的封装+传输)
  • 网络层
    • ip 协议 寻址
    • ARP 协议 从 ip 地址获取 mac 地址(局域网下)
  • 传输层:TCP、UDP
  • 应用层: http 超文本传输协议、 DNS 域名解析成 ip 地址、 FTP 文件传输协议

DNS 协议

  • DNS 服务器进行域名和对应 ip 地址转换的服务器

IP 协议

  • 寻址 通过 ip 地址定位到最终设备

ARP协议

  • 怎么通过ip地址找到mac地址的
    • ARP协议:目的就是通过ip地址找到mac地址 (在局域网下)
    • 会广播给每一个,对应到要找的IP地址会做出响应,将mac地址返回
    • ARP会有缓存记录 有记录就不用广播 缓存的是 ip:mac
    • 交换机缓存的是 mac:端口

TCP 协议

  • 传输控制协议 特点是可靠、传输效率低
  • TCP 提供全双工服务,即数据可在同一时间双向传播
  • 数据是无序的在网络间传递,接收方需要有一种算法在接收到数据后恢复原有的顺序
  • 三次握手
    • 我能主动给你打电话吗
    • 可以啊 那我也能给你打电话吗
    • 可以 建立连接成功
  • 四次挥手
    • 我们分手吧
    • 回复收到分手的信息
    • 好吧 分手
    • 行 那就到这
  • 小结
    • TCP 是双工的,所以握手需要三次,保证双方达成一致(建立连接浪费性能)
    • 当断开连接时,发送(FIN)时另一方需要马上回复(ACK),但此时可能不能立即关闭(有未发送完的数据,还有一些准备断开的操作),所以等待确认可以关闭时再发送(FIN)
  • 滑动窗口
    • 窗口大小是以字节为单位
    • 建立TCP连接时,接收方会告知自己的窗口可以接收多少字节的数据
    • 滑动窗口的目的是实现丢包重传,并且将数据有效的发送给接收方,而且可以知道每次发送多少,从而做到流量控制
    • 所以滑动窗口的核心是控制流量
    • TCP会做什么:传输的时候会做一个滑动窗口,不停地在协商滑动窗口的大小,如果值满了就停止传输,不停地发探测包,如果有了可用窗口大小,接着去传输数据。按照顺序,成功接收到一个数据之后滑动窗口会向后移动,并根据协商的结果修改窗口大小
  • 慢启动、拥塞避免、快重传、快恢复
    • 也是用来做流量控制的
    • 慢开始 超时
    • 快重传 不等超时 三次确认就立马重发

http

  • 发展历程
    • http/0.9 传输过程中没有请求头和请求体 内容采用ASCii字符流传输html
    • http/1.0 加了请求头和响应头 实现多类型数据传输
    • http/1.1
      • 持久连接 一个TCP连接上可以传输多个http请求
      • 管线化方式 每个域名最多维护6个TCP持久连接 有队头阻塞问题
      • 引入客户端cookie机制,安全机制等
    • http/2.0
      • 采用多路复用机制 一个域名使用一个TCP长链接
      • 头部压缩
      • 服务端推送
    • http/3.0 基于UDP
  • 当访问网页,发生了哪些事情
    • 客户端发送一个请求 发送的是一个域名 域名会发送给dns服务器
    • dns解析出一个ip给到客户端
    • http会把数据进行传输,http协议生成针对目标web服务器的http请求报文
    • 交给TCP进行传输:为了方便通信,将http请求报文按序号分割成报文段,把每个报文段可靠的传给对方(丢包或者超时就重发)
    • (TCP自身没有传输能力,如何传靠的是网络层)ip协议:寻址和路由 找到对方地址,通过mac地址一个个找到下一站,不停中转
    • 从对方接收到TCP报文段, 对报文段按照原来的序号进行重组报文
    • http解析传递过来的数据,对内容进行处理
    • 处理完成之后再增加一些响应信息,同样利用TCP/IP通信协议向用户进行回传

HTTP是不保存状态的协议, 使用cookie来管理状态

为了防止每次请求都进行tcp链接的建立和断开, 采用保持链接的方式keep-alive

以前发送请求后需要等待并收到响应,才能发下一个,现在都是管线化方式

http应用

  • http也是封装了一些信息和传输
  • curl -v www.baidu.com
  • http分为两部分 (发送请求 client)req -> (接收请求 server)res
  • 请求分为三部分(三部分都可以传输数据)
    • 请求行 通过方法 路径(传输的数据有限制 url大小限制)
      • 如 GET / 版本号
    • 请求头 放一些自定义信息 约定的信息 请求头不要过大
    • 请求体 传输的数据
  • 响应也分为三部分
    • 响应行
      • 如 版本号 200 ok
    • 响应头
    • 响应体
  • restFul风格
    • GET/POST/PUT/SELETE/OPTIONS
    • OPTIONS请求代表的是跨域访问时可能会出现 预检请求 试探请求 如果对方确认后 可以发真实的请求
    • OPTIONS请求只在复杂请求的状态下才能发送(get、post都是简单请求,如果增加了自定义header那么就是复杂请求)
    • OPTIONS可以定义发送的时间间隔
  • 常见的状态码
    • 可以自己设定 但是浏览器和服务器之间是有一些约定的
    • 1xx 服务器收到了信息 等到浏览器后续要做的事 websocket
    • 2xx 成功
    • 3xx 重定向 缓存
    • 4xx 客户端出错 (浏览器参数、或者服务器无法解析客户端参数)
    • 5xx 服务器错误
    • 200 请求成功
    • 204 请求成功 但是无响应内容
    • 206部分内容 分段请求
    • 301 302 永久重定向和临时重定向
    • 304缓存
    • 400 客户端请求错误
    • 401 权限问题 当前用户没登录 无权限观看
    • 403 登陆了 但是还是没有权限
    • 404 找不到
    • 405 服务器只支持get、post 但是发送了put请求 服务器就会响应找不到此方法
    • 500 请求服务解析出错了 无法完成响应
    • 502 服务期收到的内容无效
    • 503 负载均衡挂了
const http = require("http");

// 下面两种写法是等价的
const server = http.createServer(function(req,res) {
    console.log("request")
});
server.on('request', function(req,res) {
    console.log("request")
});

let port = 3000;

server.listen(3000, function()  {
    console.log('server listen on 3000')
});

// 监听错误
server.on("error", function(err){
    if(err.code === 'EADDRINUSE') { // 说明端口号被占用
        server.listen(++port);// 不用再写回调 监听成功之后会走到上面对应的回调,打印server listen on 3000
    }
})
复制代码
  • http模块对req、res的封装
const server = http.createServer(function(req, res) {
    // req是一个可读流

    // 请求行
    console.log(req.method); //大写的
    console.log(req.url); 
    console.log(req.httpVersion);

    // 请求头
    console.log(req.headers); // 统一node处理后全部都是小写

    // 请求体
    const arr = [];
    req.on("data", function(data) {
        console.log(data);
        arr.push(data);
    });
    req.on("end", function(){
        const data = Buffer.concat(arr).toString();
        console.log("end", data);
    })
})

const server = http.createServer(function(req, res) {
    // res 是一个可写流

    res.statusCode = 202;
    res.statusMessage = "my 202";
    res.setHeader("token", "ok");
    res.write("1");
    res.end("2");
});
复制代码

实现静态服务

const http = require("http");

// url组成: 协议 ://(用户名:密码)域名:端口号/资源路径?查询参数#hash
const url = require("url");
// 参数加上true 将query转成对象形式
// const {pathname,query} = url.parse("http://username:password@www.zz.com:3000/xxx?a=1#hash", true);
// pathname => /xxx

const mime = require("mime");

const server = http.createServer((req,res) => {
  const {pathname} = url.parse(req.url, true);
  // 根据路径来读取文件 /public/index.html
  const filePath = path.join(__dirname, pathname); // 获取绝对路径
  fs.readFile(filePath, function(err, data) {
    if(err) {
      res.statusCode = 404;
      return res.end('not found');
    }
    // 直接返回 浏览器可以正常展示 是因为在html中设置了 <meta charset="UTF-8">
    // 如果浏览器不给编码 浏览器显示就会乱码 
    // 所以浏览器有可能不加编码 服务器在返回数据的时候就需要添加编码格式
    res.setHeader("Content-Type", mime.getType(filePath) + ";charset=utf8");
    res.end(data);
  })
});

server.listen(3000);

复制代码
  • 写一个静态服务器
    • 官方:npm i http-server -g 可以在本地启动一个服务
    • 使用:命令行 hs 或者 http-server 默认会找public文件夹
// package.json
{
    "name": "zhuhaha-server-listen",
    "version":"1.0.0",
    "description": "",
    "main":"1.http.js",
    "bin":{
        "zsl": "./bin/www"
    }
}
/*
这个包默认是无法使用的,要把它放到全局下进行测试
使用 npm link
会生成软链 一个叫做 zhuhaha-server-listen 一个叫 zsl
*/
www文件中:
#!/usr/bin/env node

重新 npm link --fore
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享