UNP总结 Chapter 2 传输层:TCP、UDP和SCTP
注,总结中暂时忽略SCTP
1.总图
虽然称为“TCP/IP”协议族,但是本协议族还有许多其他成员,见下图
2.用户数据包协议(UDP)
UDP 套接字写入一个消息,该消息接着被封装(encapsulating)进一个UDP数据报,该UDP数据报又进而被封装成一个IP数据报,然后发送到目的地。UDP不保证UDP数据报到达其最终目的地,不保证各个数据报的先后顺序跨网络保持不变,也不保证每个数据报只到达一次。
用UDP进行网络编程所碰到的问题是缺乏可靠性,我们也称UDP提供无连接的(connectionless)服务,因为UDP客户与服务器不必存在长期的关系。
3.传输控制协议(TCP)
首先,TCP提供客户与服务器的连接(connection)。一个TCP 客户建立与一个给定服务器的连接,并跨该连接与那个服务器交换数据,然后终止连接。
其次,TCP提供可靠性(reliability)。当TCP向另一端发送数据时,它要求对端返回一个确认。如果确认没有收到,TCP自动重传数据并等待更长时间。在数次重传失败后,TCP才放弃。UDP提供不可靠的数据报传送。UDP本身不提供确认、序列号、RTT估算、超时及重传等机制。
再次,TCP提供流量控制(flow control)。TCP总是告诉对端它能够接收多少字节的数据,这称为通告窗口(advertised window)。
最后,TCP连接是全双工(full duplex)的,这意味着在给定的连接上应用进程在任何时刻既可以发送也可以接收数据。
4.TCP连接的建立和终止
1).三路握手
建立TCP的步骤:
a.服务器必须准备好接受外来的连接。这通过调用socket、bind和listen函数来完成,称为被动打开(passive open)。
b.客户通过调用connect进行主动打开(active open)。这引起客户TCP发送一个SYN( 表示同步)分片,它告诉服务器客户将在(待建立的)连接中发送的数据的初始序列号。一般 情况下SYN分片不携带数据,它只含有一个IP头部、一个TCP头部及可能有的TCP选项。
c.服务器必须确认客户的SYN,同时自己也得发送一个SYN分片,它含有服务器将在同一连接中发送的数据的初始序列号。服务器以单个分片向客户发送SYN和对客户SYN的ACK(表 示确认)。
d. 客户必须确认服务器的SYN。 连接建立过程至少需要交换三个分组,因此称之为TCP的三次握手(threeway handshake)
上图给出的客户的初始序列号为J,而服务器的初始序列号为K。在ACK里的确认号为发送这个ACK的一端所期待的对端的下一个序列号。因为SYN只占一个字节的序列号空间,所以每一个SYN的ACK中的确认号都是相应的初始序列号加1。类似地,每一个FIN(表示结束)的 ACK中的确认号为FIN的序列号加1
2).TCP选项
MSS选项。TCP发送的SYN中带有这个选项是通知对端它的最大分片大小MSS(maximum segment size)
窗口规模选项。TCP两端能够通知对端的最大窗口大小是65535,因为TCP头部相应的字段只占16位
时间戳选项。这个选项对高速连接是必要的,它可以防止由失而复得的分组可能造成的数据损坏。
3).TCP连接终止
TCP建立一个连接需三个分片,终止一个连接则需四个分片
A.某个应用进程首先调用close,我们称这一端执行主动关闭(active close)。这一端的TCP于是发送一个FIN分片,表示数据发送完毕。
B.接收到FIN的另一端执行被动关闭(passive close)。这个FIN由TCP确认。它的接 收也作为文件结束符传递给接收端应用进程(放在已排队等候该应用进程接收的任何其他数 据之后),因为FIN的接收意味着应用进程在相应连接上再也接收不到额外数据。
C.一段时间后,接收到文件结束符的应用进程将调用close关闭它的套接字。这导 致它的TCP也发送一个FIN。
D.接收到这个FIN的原发送端TCP(即执行主动关闭的那一端)对它进行确认。 因为每个方向都需要有一个FIN和一个ACK,所以一般需要四个分片。我们使用限定词“一般 ”是因为:有时步骤1的FIN随数据一起发送;另外,执行被动关闭那一端的TCP在步骤2和3 发出的ACK与FIN也可以合并成一个分片。
下图说明了这些分组的交换过程。
FIN占据1个字节的序列号空间,这与SYN相同。所以每个FIN的ACK确认号是这个FIN的序列号 加1。
4).TCP状态转移图
5).观察分组
下图说明了一个完整的TCP连接所发生的实际分组交换情况:建立连接、传送数据和终止连接。本例中客户通告的MSS(最大分片大小)值是536(表明该客户只实现了最小重组缓冲区大小),而服务器通告的MSS值为1460(以太网上IPv4的典型值)。不同方向的MSS可以不相同
注意:执行主动关闭的那一端(客户端)进入TIME_WAIT状态
另外如果连接的整个目的仅仅是发送一个单一分片的请求和接收一个单一分片的应答,那么使用TCP有8个分片的额外开销。如果改用UDP,那么只需交换两个分组:请求和应答。
5.TIME_WAIT状态
1).实现终止TCP全双工链接的可靠性,即保证tcp连接可靠断开
解释:必须处理连接终止序列四个分节中任何一个分节丢失的情况(例如,主动关闭一端发送的ACK丢失,则可能再次收到FIN,而重新发送ACK)
2).让老的重复分节在网络中消失
解释:假设在一对IP及端口上有一个连接,关闭这个连接后立即又建立起新的连接,后一个连接为前一个的化身,因为IP和端口相同,TCP必须防止来自某个连接的老分组在连接终止后再现,从而影响新连接的数据交互,所以tcp不能给处于TIME_WAIT状态的连接启动新的化身,从而被误解成属于同一连接。
至于时间规定为2MSL(最长分节生命期),TCP规定一个分节在网络中最大生存时间是MSL,这足够让某个方向上的分节最多存活MSL秒即被丢弃,另一个方向的应答最多存活MSL秒也被丢弃,通过这个规则,就能保证当成功建立一个TCP连接时,来自该链接的之前所有连接的老的重复分组在网络中已消失。
6.端口号
端口号分为三段:
1).众所周知的端口:0~1023 它们绑定于一些服务,这些服务通常确定了某种协议,例如:HTTP协议端口80
2).经注册的端口:1024~49151 它们松散的绑定一些服务,可动态分配
3).动态和私用端口:49152~65535 一般不为服务绑定这些端口,动态分配所用
7.TCP端口与并发服务器
并发服务器中主服务器循环派生子进程来处理每个新的连接,如果有多个客户端发送连接,服务器程序将用fork派生多个子进程与之通信。
假设服务器为{10.2.16.48:21},两个客户端{10.22.206.157:1500},{10.22.206.157:1501}对于服务器来说,这两个连接是有区别的,第一个连接的套接字对为{10.22.206.157:1500,10.2.16.48:21} 和第二个连接的套接字对为 {10.22.206.157:1501,10.2.16.48:21} ,两个连接分别对应于父进程或者及其子进程。
8.缓冲区大小及限制
1).TCP输出
每一个TCP套接口有一个发送缓冲区,我们可以用SO_SNDBUF套接口选项来改变这个缓冲区的大小。
TCP取套接口发送缓冲区的数据并把它发送给对端TCP,其过程基于TCP数据传送的所有规则。对端TCP必需确认收到数据,只有收到对端的ACK,本端TCP才能删除套接口发送缓冲区中已确认的数据。TCP必需保留数据拷贝直到对端确认为止。
实际上在TCP输出过程中,每个数据链路都有一个输出队列,如果该队列已满,那么新到的分组将被丢弃,并沿协议栈向上返回一个错误,从链路层到IP层,再从IP层到TCP层。TCP将注意到这个错误,并在以后某个时刻重传相应分片。应用进程并不知道这种暂时情况。
2).UDP输出
UDP套接口有发送缓冲区大小(我们可以用SO_SNDBUF套接口选项修改),不过它仅仅是写到套接口的UDP数据报的大小上限。
如果应用进程写一个大于套接口发送缓冲区大小的数据包,内核将返回一个EMSGSIZE错误。既然UDP是不可靠的,它不必保存应用程序的数据拷贝,因此无需一个真正的发送缓冲区。(应用进程的数据在沿协议向下传递时,以某种形式拷贝到内核的缓冲区,然而数据链路层在送出这些数据后将丢弃该拷贝)
UDP同样也维护着数据链路层输出队列UDP组装成数据包后就直接将其加入数据链路层输出队列,或者分片后再把每个片加入数据链路层的输出队列。如果某个UDP应用进程发送大数据报,那么它比TCP应用进程更有可能分片,因为TCP会把应用数据划分成MSS大小的块,而UDP却没有对等的手段。