目录
1、网络通信基本原理
(1)通信必要条件
- 主机之间需要有传输介质
- 主机上必须有网卡设备
- 主机之间需要协商网络速率
2、网络通讯方式
(1)常见通讯方式
- 交换机通信
- 路由器通讯
(2)如何建立多台主机互连?
(3)如何定位局域网中的其他主机?
通过 Mac 地址来唯一标识一台主机
(4)交换机的接口数量有上限,局域网存在大量主机会造成广播风暴
3、网络层次模型
(1)OSI 七层模型
- 应用层:用户与网络的接口
- 表示层:数据加密、转换、压缩
- 会话层:控制网络连接建立与终止
- 传输层:控制数据传输可靠性
- 网络层:确定目标网络
- 数据链路层:确定目标主机
- 物理层:各种物理设备和标准
数据从 A 至 B,先封装再解封
4、数据封装与解封装
(1)数据封装
(2)解封
5、TCP三次握手与四次挥手
(1)TCP 协议
- TCP 属于传输层协议
- TCP 是面向连接的协议
- TCP 用于处理实时通信
(2) 常用控制字段
- SYN = 1 表示请求建立连接
- FIN = 1 表示请求断开连接
- ACK = 1 表示数据信息确认
(3)TCP 三次握手和四次挥手
- TCP 三次握手
- 四次挥手
(4)TCP 协议
- TCP 处于传输层,基于端口,面向连接
- 主机之间要想通信需要先建立双向数据通道
- TCP 的握手和挥手本质上都是四次
- 原因:一个服务端会服务于多个客户端,我们不能保证客户端发送请求,服务端会立即把数据全部返回,所以断创建服务端
- 开连接的时候,我们要分开处理。因此挥手必须要有四次,握手可以合并为三次
6、创建TCP通信
(1)Net 模块实现了底层通信接口
(2)通信过程
- 创建服务端:接收和回写客户端数据
- 创建客户端:发送和接收服务端数据
- 数据传输:内置服务事件和方法读写数据
(3)通信事件
- listening事件:调用 server.listen 方法之后触发
- connection 事件:新的连接建立时触发
- close 事件:当 server 关闭时触发
- error 事件:当错误出现的时候触发
(4)通信事件&方法
- data 事件:当接收到数据的时候触发该事件
- write 方法:在 socker 上发送数据,默认是 UTF8编码
- end 操作:当 socket 的一端发送 FIN 包时触发,结束可读端
// server.js文件
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)
// 回数据
socket.write(Buffer.from('您好' + msg))
})
})
server.on('close', () => {
console.log('服务端关闭了')
})
server.on('error', (err) => {
if (err.code == 'EADDRINUSE') {
console.log('地址正在被使用')
}else{
console.log(err)
}
})
在终端输入命令: nodemon server.js
// client.js
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('客户端断开连接')
})
在终端输入命令: nodemon client.js
7、TCP粘包及解决
- 通信包韩数据发送端和接收端,发送端累计数据统一发送,接收端缓冲数据之后再消费
- TCP 拥塞机制决定发送机制
(1)问题:连续 client.write('拉勾教育1') ,最哦输出的结果会粘在一起
const net = require('net')
const client = net.createConnection({
port: 1234,
host: '127.0.0.1'
})
client.on('connect', () => {
client.write('拉勾教育1')
client.write('拉勾教育2')
client.write('拉勾教育3')
client.write('拉勾教育4')
client.write('拉勾教育5')
})
client.on('data', (chunk) => {
console.log(chunk.toString())
})
client.on('error', (err) => {
console.log(err)
})
client.on('close', () => {
console.log('客户端断开连接')
})
(2)解决方法:
const net = require('net')
const client = net.createConnection({
port: 1234,
host: '127.0.0.1'
})
let dataArr = [
'拉勾教育2',
'拉勾教育3',
'拉勾教育4',
'拉勾教育5'
]
client.on('connect', () => {
client.write('拉勾教育1')
for (let i = 0; i < dataArr.length; i++) {
(function (val, index) {
setTimeout(() => {
client.write(val)
}, 1000 * (index + 1));
})(dataArr[i], i)
}
})
client.on('data', (chunk) => {
console.log(chunk.toString())
})
client.on('error', (err) => {
console.log(err)
})
client.on('close', () => {
console.log('客户端断开连接')
})