通信必要条件

  • 主机之间需要有传输介质
  • 主机上必须有网卡设备(网线不能识别二进制,经过网卡的调制成高低电压)
  • 主机之间需要协商网络速率

通信条件9.png

如何建立多台主机互连?

  • 如何定位局域网中的其他主机? 通过Mac地址来唯一标识一台主机
  • 交换机的接口数量是有限的
  • 局域网存在大量主机会造成广播风暴
  • 明确目标主机IP地址

通信条件2.png
通信3.png

网络层次模式

OSI 七层模型

  • 应用层:用户与网络,应用程序与网络的接口(http ftb ssh)
  • 表示层:数据加密、转换、压缩
  • 会话层:控制网络连接建立与终止
  • 传输层:控制数据传输可靠性,需要携带目标程序的端口号
  • 网络层:确定目标网络(IP)
  • 数据链路层:确定目标主机
  • 物理层:各种物理设备和标准

作用:
更加清晰完成网络通信,

  1. TCP/IP:将前三层进行合并,统一叫做应用层
  2. 数据链路和物理层合并 叫做 接入层
  3. 中间网络层叫主机层

数据从A至B, 先封装再解封

TCP三次握手与四次挥手(有来有回)

TCP协议

  • TCP 属于传输层协议
  • TCP 是面向连接的协议
  • TCP 用于处理实时通信

基于上面的特点,TCP具有传输可靠性高的特点,但是传输效率低于UDP
TCP报文4.png

常见控制字段

  • SYN = 1表示请求建立连接
  • FIN = 1 表示请求断开连接
  • ACK = 1 表示数据信息确认

    三次握手

    CS网络架构为例:

  • 客户端向服务端发送请求连接SYN=1,服务端回应ACK=1确定请求,(建立了客户端—->服务端的数据通道)

  • 服务端向客户端发送请求连接SYN=1,客户端回应ACK=1确认请求,(建立了服务端—->客户端的数据通道)
  • 这是才算建立 双向数据通道
  • 看起来是四次,为什么说三次握手呢?

    实际处理的时候,服务端在回复客户端ACK=1的时候,同时会发送SYN = 1,请求会进行合并

cs.png
cs3.png

四次挥手

  • 客户端发送断开连接的请求,服务端回应确认,(断开了客户端—->服务端的数据通道)
  • 服务端发送断开连接的请求,客户端回应确认,(断开了服务端—->客户端的数据通道)
  • 一个服务端会服务于多个客户端

有些时候,客户端将所有的数据发给服务端,但是服务端还没有将客户端想要的数据传回,在断开连接的时候,分开处理
cs40.png

TCP 协议总结

  1. TCP 处于传输层,基于端口,面向连接
  2. 主机之间想要通信需要先建立双向数据通道
  3. TCP的握手和挥手本质上都是四次(断开的时候请求不能进行合并)

    创建TCP通信

    通信过程

  • 创建服务端:接收和回写客户端数据
  • 创建客户端:发送和接收服务端数据
  • 数据传输:内置服务事件和方法读写数据

    通信事件&方法

  • listening事件:调用server.listen方法之后触发

  • connection事件:新的连接建立时触发
  • close事件:当server关闭时触发
  • error事件:当错误出现的时候触发

  • data事件:当接收到数据时触发该事件

  • write方法:在socket上发生数据,默认是UTF8编码
  • end操作:当socket的一端发送FIN包时触发,结束可读端

    Net模块实现了底层通信接口

    ```javascript const net = require(“net”);

// 创建服务端实例 const server = net.createServer();

const PORT = 1234; const HOST = “localhost”; server.listen(PORT, HOST);

server.on(“listening”, () => { console.log(服务端已经开启${HOST}:${PORT}); });

// 接收消息,回写消息 双工流 server.on(“connection”, (socket) => { socket.on(“data”, (chunk) => { const msg = chunk.toString(); console.log(msg);

  1. // 给客户端回数据 可写流
  2. socket.write(Buffer.from("您好" + msg));

}); });

server.on(“close”, () => { console.log(“服务端关闭了”); });

server.on(“error”, (err) => { if (err.code == “EADDRINUSE”) { console.log(“地址正在被使用”); } else { console.log(err); } });

```javascript
const net = require("net");
const client = net.createConnection({
  port: 1234,
  host: "127.0.0.1",
});

// 可读流
client.on('connect',() => {
    client.write('上海')
})

client.on('data', chunk => {
    console.log(chunk.toString());
})

client.on('error',(err) => {
    console.log(err);
})

client.on('close',() => {
    console.log('客户端断开连接');
})