TCP 协议认识及应用
简介
Socket 是一套用来执行符合 TCP/IP 协议标准的网络编程接口。有时一个IP地址和一个端口号也可以叫做插口 (socket) ,这个术语最早出现在 TCP 规范 RFC793 里面。对于网络I/O来说就是用来建立tcp链接的工具,它是一个统称,不同操作系统原理相同,但接口函数却不太一样。上面是广义,狭义上术语翻译过来就叫套接字,是定义一个具备Internet通信的基本单位(例如:我们可以说建立一个套接字)。
但基本思路按照 Unix/Linux 系统的哲学"一切皆文件"来实现的。也就是说它的过程类似本地文件读写操作:
“打开open -> 读写 write/read -> 关闭 close”
通过 Socket 提供的函数在创建一个连接时,会返回一个短整数类型的描述符 (Descriptor) 来表示当前这个套接字。在 Windoes 系统叫做句柄。后面的操作也都将把这个套接字的标识作为参数带入函数中。
基本流程
基本 Socket (既不考虑多线程和有线程池的情况) 流程图如下:

上面的关闭操作是大致流程,具体请看一下内容。
TCP 连接
TCP 协议详情
TCP 所处位置和协议格式如下:

几个基本概念
报文段(message segment):在传输层逻辑划分上,每一次传输的包含 TCP 的消息内容,叫做 TCP 报文段。这一段会被继续往下被封装到网络层的 IP 数据包 (Packet) 里面。我们做 TCP 协议分析都是基于报文段来分析的。
报文段划分为两部分:一个是首部,一个是数据。
16位源/目的端口号:从这可以看出端口号的上限是 $2^16$ 大小,也就是 65535 个。所以相对此的开放式操作系统(linux, windows and so on)的端口号上限也就是这样的。
32位序列号:表示当前报文段中第一个字节的序列号。TCP 数据流中每个字节都有一个序列号。所以它能够对 $2^{32}$ >=4GB 数据进行编号。
32位确认序列号:发给对方确认的序列号,用来告诉对方本地已经接收上一次的数据,所以回个信。确认号 = 上一次接收的对方序列号 + 1。
4位首部长度:网络上也有说是数据偏移,但是理解上还是首部长度说法好理解。它表示报文段起始到数据偏移大小,也就是首部的长度。之所以只有 4 位,因为协议规定它表示的偏移长度是 32 位,而不是字面上的 1 位。所以它能够表达的最大首部长度是 4x15x32=60 字节。正常的长度是 20 个字节。
保留位:6 位的保留位,既没啥用。
6个标志位:
| 标志位 | 说明 |
|---|---|
| URG | 紧急位,为 1 时,首部中的紧急指针有效 |
| ACK | (Acknowledgment)确认位,为 1 时,首部中的确认号有效 |
| PSH | 推位,为 1 时,要求把数据尽快交给应用程序 |
| RST | 复位标志,为 1 时,复位连接,一般在出错或关闭连接时使用 |
| SYN | (Synchronization) 同步位,在建立连接时使用,当 SYN=1 而 ACK=0 时,表明这是一个连接请求报文段。对方若同意建立连接,在发回的报文段中使 SYN=1 和 ACK=1 |
| FIN | 结束位,为1时,表示发送方完成了数据发送 |
TCP连接的建立
客户端和服务器端 TCP 连接的建立也叫三次握手(three-way handshake),通过三次数据传输完成。

SYN 会占用一个序列号
TCP 的数据传输

TCP 连接的关闭

FIN 也会占用一个序列号