1. 概述
UDP是一个简单的、不可靠的数据报协议
TCP是一个复杂、可靠的字节流协议
2. 用户数据报协议(UDP)
2.1 数据报格式
16位源端口号 | 16位目的端口号 |
16位UDP长度 | 16位UDP检验和 |
数据(如果有) |
2.2 特性
UDP套接字写入一个消息,该消息接着被封装(encapsulating)进一个UDP数据报,该UDP数据报又进而被封装成一个IP数据报,然后发送到目的地。UDP不保证UDP数据报到达其最终目的地,不保证各个数据报的先后顺序跨网络保持不变,也不保证每个数据报只到达一次。
用UDP进行网络编程所碰到的问题是缺乏可靠性。为了要确保一个数据报到达其目的地,应该往应用程序中添置一大堆的特性:来自对端的确认、本端的超时和重传。
UDP提供无连接的(connectionless)服务,因为UDP客户与服务器不必存在长期的关系。
3. 传输控制协议(TCP)
3.1 数据报格式
源端口号 | 目的端口号 | |||||||
序列号 | ||||||||
确认号 | ||||||||
4位首 部长度 |
保留6位 | URG | ACG | PSH | RST | SYN | FIN |
16位窗口大小 |
16位校验和 | 16位紧急指针 | |||||||
选项 | ||||||||
数据 |
3.2 特性
首先,TCP提供客户与服务器之间的连接;
其次,TCP提供了可靠性;(确认机制、超时重传、使用序列号进行排序等机制)
再次,TCP提供流量控制;(利用通告窗口来控制,该窗口指出接收缓冲区中当前可用的空间量,从而确保发送端发送的数据不会使接收缓冲区溢出)
最后,TCP连接是全双工的,这意味着在给定的连接上应用进程在任何时刻既可以发送也可以接收数据。
3.3 TCP连接的建立和终止
3.3.1 三路握手
TCP建立连接需要3个分节,如下图所示:
服务器必须准备好接受外来的连接,称为被动打开;而客户端做为主动方,发起主动打开。通过上图可知数据包的序列号变化情况。ACK中的确认号是发送这个ACK的一端所期待的下一个序列号。
3.3.2 TCP选项
(1) MSS选项发送SYN的TCP的一端使用本选项通告对端它的最大分节大小,即MSS。
使用TCP_MAXSEG套接字选项提取和设置。
(2) 窗口规模选项在TCP数据报协议格式中可知窗口大小为16位,因此TCP连接能够通告对端的最大窗口大小为65535。为了获取更大的吞吐量,新选项可以指定通告窗口必须扩大的位数(0~14)。
使用TCP_RCVBUF套接字选项提取和设置。
(3) 时间戳选项
3.3.3 TCP连接终止
TCP连接终止通常需要4个分节,如下图所示:
这边所指的“通常”是由于:某些情形下步骤1的FIN可能随数据一起发送;另外,步骤2和3发送的分节都出自执行被动关闭那一端,有可能合并成一个分节。
半关闭状态,是指从步骤2到步骤3之间,执行被动关闭一端到执行主动关闭一端流动数据是可能的。
3.3.4 TCP状态转化图
3.3.5 观察分组
3.3.6 TIME_WAIT状态
该状态是执行主动关闭的那端需经历的状态。该时间为2MSL,MSL是任何IP数据报能够在因特网中存活的最长时间。
存在的理由有两个:
(1) 可靠的实现TCP全双工连接的终止;
(2) 允许老的重复分节在网络中消逝。
3.4 端口号
(1)众所周知的端口为0~1023;
(2)已登记的端口为1024~49151;
(3)49152~65535是动态的或私用的端口。
套接字对
四元组:本地IP地址、本地TCP端口号、外地IP地址、外地TCP端口号。
套接字对唯一标识一个网络上的TCP链接。
3.5 缓冲区大小与限制
·IPv4要求的最小链路MTU是68字节;
·两个主机之间相反的两个方向上路径MTU可以不一致;
·MTU会导致IP数据包进行分片;这些片段在到达目的地之前通常不会被重组;
·IPv4首部中的“不分片”位(DF位)若被设置,那么不管是发送这些数据包的主机或者转发它们的路由器,都不允许对它们进行分片;
IPv4首部中的“不分片”位(DF位)可用于路径MTU的发现;
·最小重组缓冲区大小,是IPv4的任何实现都必须保证支持的最小数据报的大小;
·TCP有一个MSS,目的是告诉对端重组缓冲区大小的实际值,从而试图避免分片。MSS经常设置成MTU减去IP和TCP首部的固定长度。
3.5.1 TCP输出
每个TCP套接字有一个发送缓冲区,可以使用SO_SNDBUF套接字选项来更改大小;
从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用程序已接收到数据。
只有收到对端的ACK,本端TCP才能从发送缓冲区中丢弃已确认的数据。
实际上在TCP输出过程中,每个数据链路都有一个输出队列,如果该队列已满,那么新到的分组将被丢弃,并沿协议栈向上返回一个错误,从链路层到IP层,再从IP层到TCP层。TCP将注意到这个错误,并在以后某个时刻重传相应分片。应用进程并不知道这种暂时情况。
3.5.2 UDP输出
UDP套接口有发送缓冲区大小(我们可以用SO_SNDBUF套接口选项修改),不过它仅仅是写到套接口的UDP数据报的大小上限。
UDP同样也维护着数据链路层输出队列UDP组装成数据包后就直接将其加入数据链路层输出队列,或者分片后再把每个片加入数据链路层的输出队列。
从写一个UDP套接字的write调用成功返回表示所写的数据报或其所有片段已被加入数据链路层的输出队列。