概述
焦点是TCP UDP SCTP,UDP是简单的不可靠的数据报文协议,TCP是复杂可靠的字节流协议,SCTP支持消息边界,传输级别多宿和头段阻塞最小的
总图
- IPv4 使用32位地址,为TCP UDP SCTP ICMP IGMP 提供分组递送服务
- IPv6使用128位地址
- TCP面向连接,全双工,关注确认、超时、重传、可以使用v4和v6,使用流套接字
- UDP 无链接,使用数据报套接字,不保证传输到
- SCTP 流控制传输协议, 全双工面向链接,
- ICMP 网际控制消息协议 处理在路由器和主机间流通的错误和控制消息
- ARP 地址解析,将IPv4地址映射为硬件地址
- IGMP 网际组管理协议,用于多播
UDP
- 是无连接的,创建一个套接字发送数据,然后可以马上用同一个套接字发送数据给另一个服务器
- 不可靠传输,不保证报文到达最终目的地,不保证先后顺序不变,也不保证每个数据报只到达一次,
- 传输的是报文流,报文就是记录边界,报文长度会随数据一同传递给接受端
- 为了确保到达目的地,往往添加来自对端的确认,本段的超时重传。
TCP
- 面向连接的,开始通信前要和给定服务器建立连接,然后终止链接
- 可靠传输,传输过程要求对段返回确认,否则自动重传数据。
- TCP根据字节对应的***对数据进行排序,这样接收端可以根据***重排数据,或者丢弃重复数据。
- 提供流量控制,告知对段自己能够接收的数据大小,该窗口指出缓冲区中的可用空间。窗口是动态变化的,接收数据时,窗口大小减小,应用从缓冲区读取数据时,窗口增大。若窗口大小为0,说明缓冲区满了。
SCTP
- 在C/S之间提供关联,并提供可靠性,排序,流量控制,关联是指两个系统之间的通信,而不止一个IP地址
- SCTP面向消息的,提供按顺序传输功能,发送段将长度写入每个消息
- 可在端点之间提供多个流,每个流各自可靠地递送消息。一个消息的丢失不会阻塞同一关联其他流上消息的传递,与TCP正好相反
- 多宿,在同一个关联内支持多个IP地址,
TCP的建立和终止
握手
- 服务器准备连接,通常经过
socket() bind() listern()函数完成 - 客户端调用
connect()主动打开, 同时发送一个SYN (同步)给服务器,并标记seq,所在的报文只有IP首部,TCP首部和选项,进入SYN_SENT - 服务器返回一个SYN,同时包含服务器接受到的seq,和ACK,进入
SYN_RCVD - 客户返回一个ACK,此时
connect()返回,ACK是上次接收的seq+1,发送后客户建立连接,服务器接受到ACK后也建立连接,此时accept()返回
SYN占据一个字节的***空间,所以每个SYN中对应的ACK的序号就是SYN的初始***+1
TCP选项
- MSS 通告最大分节大小,就是在本连接的每个TCP分节接受的最大数据量,发送端使用MSS作为最大大小
- 窗口规模选项,(前提是两个系统必须都支持),默认最大65535,可扩展到接近1gb
- 时间戳选项
终止
- 客户端调用
close()发送一个FIN分节,即执行主动关闭,进入FIN_WAIT_1 - 接受到FIN的服务器 返回ACK,之后客户端进入
FIN_WAIT_2,服务器将终止连接传递给应用进程,进入CLOSE_WAIT - 一段时间后服务器调用
close(),再次发送FIN 进入LAST_ACK, - 客户端接受到FIN后,发送ACK对这个FIN进行确认 ,进入
TIME_WAIT等待2MSL后关闭连接
需要注意的是,被动关闭端有可能将FIN和ACK进行合并
对于TIME_WAIT,经历的时间是2×IP数据报在网络中存在的最长时间,它的作用是
- 实现TCP连接正常关闭,如果客户端最终的ACK丢失,服务器会重发FIN,这时在
TIME_WAIT中的客户端就可以重发ACK,避免不正常关闭 - 使得老的分节(包括一端的请求和另一端的回复)在网络中消失,避免新的连接收到老的分节。
端口
- 0~1023是IANA众所周知端口,1024~49151是注册端口。49152~65535是动态端口
- 套接字对定义了连接的两个端点,<本地IP,本地TCP端口,远程IP,远程TCP端口>,ip地址+端口号成为套接字
-
{*:21,*:*}这个套接字对在任意本地地址21端口等待连接请求,服务器可指定接受到特定本地接口的外来连接,选择一个或者任意一个,服务器不能指定地址清单。任意地址即INADDR_ANY - 服务器接收连接时,fork一个子进程接受请求,子进程中拥有的是已连接套接字而父进程中是监听套接字。TCP无法通过目的端口号来分离不同分节,必须查看套接字对的所有四个元素。
缓冲区大小
- IPv4最大65535字节,IPv6 65575字节,它有一个特大净荷来扩展净荷长度字段到32位,(默认16位)
- 以太网的MTU为1500, IPv4最少MTU是68字节(20固定长度+最多40选项),IPv6要求最少1280字节。路径MTU指两个主机之间最小的MTU,两个主机相反方向MTU可以不一致
- 如果IP数据报超过了MTU,v4和v6都会进行分片,v4主机对产生的数据报分片,v4路由对转发的分片,v6主机对产生的分片,v6路由不对转发的分片
- 如果DF位被设置,则即使超过了MTU也不进行分片,如果v4路由接收到了超过MTU且DF位设置的数据报,产生一个出错消息。因此它被用来探测路径上MTU,如果设置DF,且及收到了ICMP出错报文,就减小MTU再重新发送
- v4和v6定义了最小缓冲区大小,是任何实现都必须保证支持的最小数据报大小,v4是576字节,v6是1500字节,
- TCP的MSS通告每个分节最大TCP数据量,往往是MTU-IP首部-TCP首部,IPv4 1460, IPv6 1440,在TCP的MSS选项中,最大值为65535,这对IPv4适用,但对IPv6:(1)无特大净荷的,TCP最大数据量65515 (2) 有特大净荷选项,对端通告MSS 65535,则数据报大小为路径MTU
TCP输出
- 每个TCP套接字有发送缓冲区,通过
SO_SNDBUF更改缓冲区大小,调用write时内核从应用程序缓冲区复制数据到套接字缓冲区,如果套接字缓冲区大小不足,则应用程序阻塞,直到全部数据复制到套接字缓冲区。故write返回只说明应用程序缓冲区可使用,不代表TCP对端接受到数据。 - TCP提取套接字缓冲区并发送对端,收到ACK后才能从发送缓冲区丢弃数据,TCP需要为已经发送的数据保留副本,直到被对端确认
- TCP以MSS或者更小的块将数据传给IP,并添加TCP首部,MSS为对端通告值或者536(576-20IP首部-20TCP首部)IP添加IP首部,按照地址查找路由,传输给数据链路,IP可能进行分片,但是MSS可以避免分片。
UDP输出
- UDP套接字有发送缓冲区大小,但仅仅是UDP数据报的大小上限。如果应用写大于套接字发送缓冲区大小的数据报,内核返回EMSGSIZE错误,UDP不必保存发送数据的副本,就不需要一个实际的发送缓冲区
- UDP为用户数据加上UDP头传递给IP,IP添加IP首部,然后传输给数据链路,如果UDP发送了大于MTU的数据报,有可能会被IP分片。(TCP可以通过MSS来避免分片)
- 写一个套接字成功表示数据报已经被加入到数据链路层的输出队列,如果队列没有足够的空间,内核通常返回ENOBUFS
常见协议
TCP滑动窗口
- TCP两端交换信息如***,ACK,窗口大小,发送段调节窗口大小控制发送,窗口大小字段长16位,想对于ACK有一个字节偏移量,位于TCP头中
- TCP连接维护一对窗口,发送端分为已发送已确认、已发送未确认、尚未发送、不允许发送四个部分,收到对应窗口左端***的ACK时,窗口左端移动。接收端分为已接收已确认、允许接收、不允许接收,收到对应窗口左端***的数据并发送ACK后,窗口滑动。
- 发送端通过ACK可以得知下一个要发送的***和当前接收端的窗口大小(进而实现了流量控制)。
- 在接收端零窗口情况下,发送端采用一个计时器询问接收端窗口是否增长,强制要求接收端返回ACK