网络模型

net_osi7_tcp_ip5.png

TCP 协议

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。相

  • 面向连接:需要对方主机在线,并建立链接
  • 面向字节流:引入了数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件
  • 可靠:对于数据包丢失的情况,TCP 提供重传机制

440ee50de56edc27c6b3c992b3a25844.png

三次握手

Client: I want to talk to you.
Server: Yes. I would very much appreciate sharing communications with you. Are you ready to begin communications?
Client: … Yes.

四次挥手

A:B 啊,我不想玩了。
B:哦,你不想玩了啊,我知道了
B:A 啊,好吧,我也不玩了,拜拜。
A:好的,拜拜。

Socket

Socket源于Unix,而Unix的基本哲学是『一些皆文件』,都可以用『打开open ==> 读/写(read/write) ==> 关闭(close)』模式来操作,Socket也可以采用这种方法进行理解。

  • 可以实现底层通信,几乎所有的应用层都是通过socket进行通信的,因此『一切且socket』
  • TCP/IP 协议族中,传输层存在两种通用协议: TCP、UDP,两种协议不同,因为不同参数的 socket 实现过程也不一样

微信截图_20210306095858.png

Net 模块构建一个 TCP 服务

该模块是基于 TCP 协议的 socket 网络编程模块,可以用于创建基于流的 TCP 或 IPC 的服务器(net.createServer())与客户端(net.createConnection())

TCP 粘包(小包合并)问题

客户端(发送的一端)在发送之前会将短时间有多个发送的数据块缓冲到一起(发送端缓冲区),形成一个大的数据块一并发送,同样接收端也有一个接收端缓冲区收到的数据先存放接收端缓冲区,然后程序从这里读取部分数据进行消费,这样做也是为了减少 I/O 消耗达到性能优化。

解决方案:

  • 延迟发送
  • 关闭 Nagle 算法
  • 封包/拆包

    封包/拆包

  • 把消息的尺寸与消息一块发送

    使用长度编码的方式,通信双方约定好格式,将消息分为定长的消息头(Header)和不定长的消息体(Body),在解析时读取消息头获取到内容占用的长度,之后读取到的消息体内容字节数等于字节头的字节数时,我们认为它是一个完整的包。

  • 发送端:封包

    给一段数据加上包头

  • 接收端:拆包

  1. 为每一个连接动态分配一个缓冲区,同时把此缓冲区和SOCKET关联.
  2. 当接收到数据时首先把此段数据存放在缓冲区中.
  3. 判断缓存区中的数据长度是否够一个包头的长度,如不够,则不进行拆包操作.
  4. 根据包头数据解析出里面代表包体长度的变量.
  5. 判断缓存区中除包头外的数据长度是否够一个包体的长度,如不够,则不进行拆包操作.
  6. 取出整个数据包.这里的”取”的意思是不光从缓冲区中拷贝出数据包,而且要把此数据包从缓存区中删除掉.删除的办法就是把此包后面的数据移动到缓冲区的起始地址.

    参考资料

  7. 初步研究node中的网络通信模块

  8. 基于 Nodejs 的 Tcp 封包和解包的理解
  9. 入门 Node.js Net 模块构建 TCP 网络服务