🌚

⬅ Click Here

从OSI七层模型到TCP

为什么要写这篇博客

一个是感觉自己的计算机网络基础薄弱,关于七层模型和 tcp、udp 看过几次了,都不够透彻,知其然不知其所以然。再一个,最近和同事有聊到这个事,感觉自己也说不明白,又意识到很重要,所以决定整理一下,自己感觉自己会了和可以给别人讲明白这个事儿,区别还是很大的啊。就参考资料和自己理解记录一下。

先说什么是网络协议

两台设备进行网络通信时,双方要提前约定一些规则。这样才可以让对方设备理解你要做什么。比如,如何发起通信,如何发出/接收数据,如何关闭链接。

再说 OSI 7 层模型 和 TCP/IP 4 层模型

OSI(Open System Interconnection) 开放式系统互联参考模型,为了统一处理,模块化,易于维护,OSI 采用分层结构。包含七层,每一层实现各自的功能和协议,通过接口提供给更高一层并完成与相邻层的接口通信。

IOS 7 层模型是一种网络通信理论模型。其含义就是推荐所有公司使用这个规范来控制网络。这样所有公司都有相同的规范,设备就能互联了。OSI 参考模型是学术上法律上的国际标准,是完整的权威的网络参考模型

关系如下:

OSI 7 层模型 功能 传送介质 对应 TCP/IP 4 层模型 对应协议
应用层 Application 为应用进程提供网络服务。 报文 应用层 HTTP、FTP、SMTP
表示层 Presentation 数据格式化,加密和解密。 报文 应用层 Telnet、Rlogin、SNMP、Gopher
会话层 Session 建立应用和应用之间的连接。 报文 应用层 SMTP、DNS
传输层 Transport 建立设备和设备之间的连接。 报文 传输层 TCP、UDP
网络层 Network 为数据包选择路由,寻址。 数据包 网络层 IP、ICMP、ARP、RARP、AKP、UUCP
数据链路层 Data Link 根据以太网协议将一组电信号组成一个数据包,称作”帧”,控制传输。通俗说,就是控制数据在网线、光纤传输。 数据帧 链路层 FDDI、Ethernet、Arpanet、PDN、SLIP、PPP
物理层 Physical 把网线,光纤将设备链接起来组网。物理传输介质。 比特流 链路层 IEEE 802.1A、IEEE 802.2 到 IEEE 802.11

TCP/IP 4 层模型 (协议簇)

TCP/IP 协议簇是 internet 的基础,是多个协议的统称,命名为 TCP/IP 是因为TCPIP是其中很重要的两个协议。

TCP/IP 分为四层,每一个层都有各自的协议和功能,其中 TCPUDP 协议位于 TCP/IP 协议簇的传输层。

TCP/IP 借鉴了 OSI 的分层概念建立TCP/IP模型,TCP/IP 已被广泛使用,成为网络互联事实上的标准

使用 TCP/IP 协议传递数据图解:

image-20220306115359466

TCP

TCP(Transmission Control Protocol
)全称是传输控制协议,是一种面向连接的可靠的全双工单播传输的基于字节流的传输层通信协议。属于TCP/IP协议簇的传输层。

  • 面向连接: 即传递数据前在两端建立连接,使用“三次握手”确保两端的发送和接收能力,提供可靠的连接
  • 仅支持单播传输:只能进行一对一的数据传输,不支持组播和广播传输方式。
  • 拥堵控制:网络拥堵的时,TCP能够减小向网络注入数据的速率和数量,缓解拥堵,提供对流量控制和服务质量的访问。
  • 全双工: 双端既可以当接收者,也可以当发送者
  • 基于字节流模式: 比如发送端发送 100 字节到目标端,目标端可以分 10 次,每次 10 字节接受,也就是以少量数据分以任意次接收

UDP

UDP(User Data Protocol)全称用户数据报协议,是一种无连接的不可靠的支持组播和广播基于数据报的传输层通信协议。属于TCP/IP协议簇的传输层。

  • 无连接不可靠: 不需要繁琐的三次握手,确认、重传、拥塞控制等机制,没有这些安全机制,速度更快的同时,安全性变差,易丢包。UDP 使用尽可能最大努力交付,但不保证可靠交付。
  • 支持组播和广播: 可以一对一一对多多对一多对多数据传输。
  • 基于数据报模式: 一次发送对应一次接收,一次只读取一个报文,多个报文不可以合并。

UDP 和 TCP 区别总结

指标 TCP UDP
连接 面向连接 无连接
报文 面向字节流 面向报文
效率
是否可靠 可靠 不可靠
拥塞控制
速度
双共性 全双工 一对一、一对多、多对一、多对多

使用 nodejs 实现 TCP 连接

服务端

const net = require("net");
const HOST = "127.0.0.1";
const PORT = 8081;
const server = net.createServer();
server.on("listening", () => {
  console.log(`TCP server at ${HOST}:${PORT}`);
});
server.on("connection", (socket) => {
  socket.on("data", (buffer) => {
    const msg = buffer.toString();
    console.log(msg);
    socket.write(Buffer.from(`来自服务端 ${msg}`));
  });
});
server.on("close", () => {
  console.log("TCP server close!");
});
server.on("error", (err) => {
  console.error(`TCP server error :${err}`);
  setTimeout(() => {
    server.close();
  }, 1000);
});
server.listen(PORT, HOST);

客户端

const net = require("net");
const HOST = "127.0.0.1";
const PORT = 8081;
const client = net.createConnection({
  host: HOST,
  port: PORT,
});
client.on("connect", () => {
  setTimeout(() => {
    client.write("客户端向服务端发送消息: 1");
  }, 1000);
  setTimeout(() => {
    client.write("客户端向服务端发送消息: 2");
  }, 2000);
  setTimeout(() => {
    client.write("客户端向服务端发送消息: 3");
  }, 3000);
});
client.on("data", (buffer) => {
  console.log(buffer.toString());
});
client.on("error", (err) => {
  console.error("TCP server error", err);
});
client.on("close", (err) => {
  console.log("client disconnects", err);
});

903kj94rnyoOIrs

使用 nodejs 实现 UDP 连接

服务端

const dgram = require("dgram");
const HOST = "127.0.0.1";
const PORT = 8082;

const server = dgram.createSocket("udp4");

server.on("listening", function () {
  const address = server.address();
  console.log(`UDP server at ${HOST}:${PORT}`);
});

server.on("message", function (message, remote) {
  console.log(`来自服务端 ${message}`);
});

server.bind(PORT, HOST);

客户端

const dgram = require(`dgram`);
const PORT = 8082;
const HOST = "127.0.0.1";

const client = dgram.createSocket("udp4");

setTimeout(() => {
  sendMsg(Buffer.from(`客户端向服务端发送消息: 1`));
}, 1000);

setTimeout(() => {
  sendMsg(Buffer.from(`客户端向服务端发送消息: 2`));
}, 2000);

setTimeout(() => {
  sendMsg(Buffer.from(`客户端向服务端发送消息: 3`));
}, 3000);

setTimeout(() => {
  client.close();
  console.log("客户端主动关闭");
}, 4000);

function sendMsg(_msg) {
  client.send(_msg, PORT, HOST, function (err, bytes) {
    if (err) throw err;
    console.log(_msg.toString());
  });
}

image-20220222230031275

· 2022年2月22日 · 被浏览 -