高级 C 与网络编程复习(2)—— 传输层:TCP、UDP、SCTP(第二章)
总图(Big Picture)
UDP
- UDP 应用程序将数据封装到 UDP 数据报,,并将其写到 UDP socket。进而封装成 IPV4 或 IPV6 数据报(datagram),然后发送到目的地
- UDP 提供的是无连接的服务(connectionless service)
- 每个 UDP 数据报都有一个长度,如果一个数据报正确地到达目的地,那么数据报的长度将随数据一道传递给接收端应用程序
- RFC 768 [Postel 1980]
TCP
- 面向连接(Connection-oriented)
- 提供可靠传输(Reliable)
- TCP 通过给每个字节关联一个***(sequence)对所发送的数据进行排序(sequencing)
- TCP 提供流量控制(flow control)==> 控制接收端收包的速率
- 全双工(full-duplex)
TCP 连接的建立和终止
-
三路握手 ———— Three-Way Handshake (SYN, ACK)
-
服务器通过 socket,bind,listen 创建一个监听 socket,并调用 accpet 准备接受外来的连接(这些工作要在客户端请求来临之前做好)。
-
客户端通过 socket 函数创建一个未连接的 socket,再调用 connect 尝试连接到服务器(此时客户端阻塞,等待服务器响应)。此时会向服务器发送一个 SYN 包(表明客户端欲向服务器申请服务),等待服务器的确认。
-
服务器收到 SYN 包,则向客户端发送一个 ACK(告诉客户端,请求我已经收到)。同时发送一个 SYN(通知客户端服务器需要知道客户端是否收到回复,收到则请回一个 ACK)
-
客户端收到服务器发回的 ACK 和 SYN 之后,connect 函数返回(表示连接服务器成功),并向服务器回一个 ACK(告知服务器我已经收到你的回复)
-
服务器收到客户端的 ACK 以后 accept 函数返回(此时连接正式建立,可以开始后通信)
- ACK 如果不捎带数据的话,是不占***的
- SYN 占一个***
-
-
四路终止 ———— Four-Way Termination (FIN, ACK)
-
客户端调用 close(任意一端都可以发起终止,此处以客户端发起为例,发起终止的一端称为执行主动关闭)。接着向服务器发送一个 FIN,表示数据发送完毕
-
服务器接收到 FIN 后回复一个 ACK(此时服务器称为执行被动关闭的一端),同时服务器的 read 函数会读到一个 EOF,导致 read 函数退出
-
一段时间后,服务器也调用 close,向客户端发送一个 FIN
-
客户端收到 FIN 以后回复一个 ACK
- FIN 占一个***
- 在被动关闭一端收到 FIN 到其调用 close 函数之间的间隙,称为半关闭状态(half-close),在这段时间内理论上仍然有发送数据的可能(但是通过 close 方式关闭的话,时无法再进行通信的,因为 close 会同时关闭写一端和读一端,后面接收 shutdown 就可以只关闭写或读)
- 当一个 Unix 进程无论自愿(调用 exit 或 main 函数返回)还是非自愿(收到一个终止本进程的信号)的终止时,所有打开的描述符都将被关闭,这也导致主机向仍然打开的任何 TCP 连接上发出一个 FIN(对于那些描述符只被这个终止的进程持有的连接而言)
-
TCP 状态转换图
- 上述状态转移图中的细线表示的是可能执行的路线。粗线和虚线表示的是 TCP 服务器和客户端正常情况(或说大多数情况)走的状态转移路线。
- 当发生错误,或遇到一些比较凑巧的事件,就可能走细线指向的转移路线
- 举例来说:途中有一条细线是 SYN_SENT ——> SYN_RCVD 的
- 这种情况可能是客户端发出了一个 SYN 到服务器,并希望服务器回一个 ACK 和一个 SYN
- 但是由于一些不可预知的错误,服务器返回的 SYN 和 ACK 只有 SYN 回到了客户端,而 ACK 则延迟了或丢了
- 这个时候客户端的状态就转移到了 SYN_RCVD。之后一旦收到 ACK(可能是服务器发送的消息丢包后重传,也可能是延迟的消息到达了),则客户端的状态可正常转移到 ESTABLISHED 状态
TCP 的限制
- TCP 同时提供可靠数据传输和严格的有序数据分发。然而有一些应用程序需要可靠数据传输,但是不需要顺序维护,而另一些应用过程序只需要部分有序即可。
- TCP 这种面向数据流的传输方式有时候是不方便的。应用程序必须添加自己的记录标记。
- TCP 套接字的范围有限,使得为多宿主主机提供高可用数据传输能力的任务变得复杂
- 容易受到拒绝服务攻击,例如 SYN 攻击
- 这些限制影响公共交换电话网的 IP 性能
端口号(Port Numbers)
- 众所周知(well-know)的端口:0 ~ 1023
- 已注册端口:1024 ~ 49151
- 动态或私有端口:49152 ~ 65535
TCP 端口号与并发服务器