TCP 涉及的知识点
- TCP 在 ISO/OSI 中的位置
- TCP 旁可对比 UDP
- TCP 上可追溯 HTTP, SSH, FTP
- TCP 内可探究三次握手和四次挥手、流量控制、拥塞控制、粘包/拆包
- TCP 下可溯源 IP
声明: 由于涉及的知识较广泛, 本篇文章是为了展开或者拓宽 TCP 相关的知识, 所以深入还需多看看提供的参考文章, 或者自行查阅相关资料.
1. TCP 在 ISO/OSI 中的位置
ISO/OSI: 国际标准化组织/Open System Interconnection
所在位置: 传输层

2. TCP 旁可对比 UDP
2.1 TCP/IP
TCP: Transmission Control Protocol, 传输控制协议
TCP 是双端连接的, 其双端是通过三次握手建立的连接.
那么为什么要三次握手?
防止失效的连接请求报文段被服务端接收,从而产生错误。
具体参考: tcp为什么要三次握手,而不能二次握手?
TCP 是可靠的双端连接, 可靠在于它是双端的, 而且会对分组/数据包进行校验, 如果丢失的分组还会重发, 保证了数据的完整性. 所以适合用来传输文件等.
但是 TCP 断开连接还要四次挥手.
具体参考: 【漫画】TCP第四次挥手时,为啥要等待2MSL才进行关闭?
2.2 UDP/IP
UDP: User Datagram Protocol, 用户数据包协议
UDP 无需建立连接, 没有状态, 分组头部开销较小.
所以无连接就不可靠, 没有拥塞控制, 无法保证数据的完整性. 但是就因此传输的效率很高. 一般用于实时视频等方面.
具体参考: UDP
3. TCP 上可追朔 HTTP, SSH, FTP
这里就选择 HTTP 来说吧
HTTP/1 是基于 TCP/IP 的进行传输数据的. 但是连接无法复用, header携带内容过大导致协议开销大, 传输的都是明文导致安全性差, 对头阻塞等.
HTTP/2 基于SPDY3, 专注于性能, 最大的一个目标是在用户和网站间只用一个连接. 它采用了二进制格式传输数据, 引入了 I/O多路复用, Header 压缩等因此提高了性能. 现在大部分还在使用 HTTP/1, 但抖音已经使用的是 HTTP/2.
HTTP/3 是 Google 另起炉灶, 搞起了 QUIC 协议, 这个协议基于 UDP, 但同时也汲取了 TCP 的优点, 实现了即快又可靠的协议. 对缓存建立了加密和验证, 优化了 I/O多路复用, 对报文加密认证, 前向纠错机制. 但用之好像少之又少, 不过相信在这 5G 时代里, 很快就能够探到它的身影.
具体参考: HTTP/3 竟然基于 UDP,HTTP 协议这些年都经历了啥?
附加问题: 对 HTTP 的 Header 了解吗?
附 I/O 多路复用
I/O 多路复用是五种 IO模型中最常用的一种模型.

从这个 IO 模型中, 你会经常发现这三个词: select, poll, epoll.
Select
sokect 是通过一个 select() 系统调用来 监视多个文件描述符,当 select() 返回后,该数组中 就绪的文件描述符便会被该内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。 select 的 优点是支持跨平台, 缺点在于 单个进程能够监视的文件描述符的数量存在最大限制。 另外 select() 所维护的存储大量文件描述符的 数据结构,随着文件描述符数量的 增大,其 复制的开销也线性增长。同时,由于 网络响应时间的延迟使得大量 TCP 连接处于非活跃状态,但 调用 select() 会对所有 socket 进行一次线性扫描,所以这也浪费了一定的开销。
文件描述符 fd
文件描述符是一个用于表述指向文件的引用的抽象化概念。 文件描述符在 形式上是一个非负整数, 实际上它是一个索引值,指内核为每一个进程所维护的进程打开文件的记录的记录表, 当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。
poll
poll 和 select 在本质上没有多大差别,但是 poll 没有最大文件描述符数量的限制。 poll 和 select 存在同样一个缺点就是,包含大量文件描述符的 数组被整体复制于用户态和内核的地址空间之间,而 不论这些文件描述符是否就绪,它的 开销随着文件描述符数量的增加而 线性增大。 另外,select() 和 poll() 将就绪的文件描述符告诉进程后,如果进程没有对其进行 IO 操作,那么下次调用 select() 和 poll() 的时候将 再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为 水平触发(Level Triggered)。
epoll
epoll 可以同时支持水平触发和边缘触发(Edge Triggered, 只告诉进程哪些文件描述符刚刚变为就绪状态,它 只说一遍,如果我们 没有采取行动,那么它 将不会再次告知,这种方式称为 边缘触发),理论上,边缘触发的性能要更高一些,但是代码实现相当复杂。 epoll 同样只告知那些就绪的文件描述符,而且当我们调用 epoll_wait() 获得就绪文件描述符时,返回的不是实际的描述符, 而是一个代表就绪描述符数量的值,你只需要去 epoll 指定的一个数组中依次取得相应数量的文件描述符即可,这里也 使用了内存映射(mmap)技术,这样便 彻底省掉了这些文件描述符在系统调用时复制的开销。 另一个本质的改进在于 epoll 采用基于事件的就绪通知方式。在 select/poll 中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而 epoll 事先通过 epoll_ctl() 来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似 callback 的回调机制,迅速激活这个文件描述符,当进程调用 epoll_wait() 时便得到通知。
4. TCP 内可探究粘包/拆包
三次握手和四次挥手,在以上的部分中已经提到过,这里主要讲粘包和拆包
粘包原因: 传输中的分组没有数据边界
拆包就是对粘包的解决办法: 发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。
具体参考: socket编程 TCP 粘包和半包 的问题及解决办法
5. TCP 下可朔源 IP
5.1 IP 的五种类型
A 类: IP地址可选用范围 (0.0.0.0 至 127.255.255.255)
B 类: IP地址可选用范围 (128.0.0.0 至 191.255.255.255)
C 类: IP地址可选用范围 (192.0.0.0 至 223.255.255.255)
D 类: IP地址可选用范围 (224.0.0.0 至 239.255.255.255)
E 类: IP地址可选用范围 (240.0.0.0 至 255.255.255.254)
具体参考: ip分类
5.2 局域网和广域网
局域网,英文名字Local Area Network,缩写为LAN。
广域网,英语名字为Wide Area Network,缩写为 WAN,又称广域网、外网、公网.
具体参考: 局域网和广域网