Linux高性能服务器编程——ch3笔记

第3章 TCP 协议详解

3.1 TCP服务的特点

面向连接:在数据读写前必须先建立连接,并分配内核资源。全双工(读写可以通过一个连接进行)。数据交换后必须断开连接,释放系统资源。 一对一的,基于广播和多播(目标是多个主机地址)的应用程序不能使用TCP。
字节流:发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,应用程序对数据的发送和接收是没有边界限制的,在TCP发送(接收)缓冲区封装(读出)。
Linux高性能服务器编程——ch3笔记_第1张图片
可靠传输:发送应答、超时重传,TCP报文段最终是以IP数据报发送的,而IP数据报到达接收端可能乱序、重复,所以TCP协议还会对接收到的TCP报文段重排、整理,再交付给应用层。

3.2 TCP头部结构

Linux高性能服务器编程——ch3笔记_第2张图片
确认号:收到的TCP报文段的序号值加1。
MSS = MTU - 20 - 20

3.3 TCP连接的建立和关闭

Linux高性能服务器编程——ch3笔记_第3张图片
TCP连接由客户端发起,并通过三次握手建立。
确认报文段 5 是可以省略的,因为结束报文段 6 也携带了该确认信息。
确认报文段 5 是否出现在连接断开的过程中,取决于 TCP 的延迟确认特性。
半关闭状态(shutdown函数):全双工连接,允许两个方向的数据传输被独立关闭,通信的一端可以发送结束报文段给对方,告诉它本端已经完成了数据的发送,但允许继续接收来自对方的数据,直到对方也发送结束报文段以关闭连接。若此时客户端未等服务器关闭连接就强行退出,此时客户端连接由内核接管(孤儿连接)。
Linux高性能服务器编程——ch3笔记_第4张图片
read系统调用返回0(收到结束报文段)确认对方关闭连接。
iptable命令:过滤数据包
每次超时重连时间都增加一倍。

3.4 TCP状态转移

CLOSED开始:
Linux高性能服务器编程——ch3笔记_第5张图片
虚线:服务器端,listen系统调用,被动连接
实线:客户端,connect系统调用,主动连接,失败原因:1)目标端口不存在(未被任何进程监听),或者端口被处于TIME_WAIT状态的连接占用,则服务器向客户端发送一个复位报文段;2)端口存在,但超时未收到确认报文段。
Linux高性能服务器编程——ch3笔记_第6张图片
报文段6后,客户端并未直接进入CLOSED,需要等待2 x MSL(TCP 报文段在网络中的最大生存时间)时间才能完全关闭。
原因:1)可靠地终止连接;2)保证让迟来的 TCP 报文段有足够的时间被识别并丢弃。
此时将无法立即使用该连接占用着的端口来建立一个新连接,因为TCP端口不能被同时打开多次。客户端一般使用系统自动分配的临时端口号来建立连接,而由于随机性,临时端口号一般和程序上一次使用的端口号(还处于 TIME-WAIT 状态的那个连接使用的端口号)不同,所以客户端程序一般可立即重启,除非强制使用上一次端口且未超时2 x MSL(考虑服务器主动关闭但异常终止,原因是使用同一知名服务端口号,可通过socket选项SO_REUSEADDR强制进程立即使用该端口)。

3.5 复位报文段

RST标志:通知对方关闭连接或重新建立连接。
1)访问不存在端口(或端口处于TIME_WAIT),复位报文段的接收通告窗口大小为0,无法回应;
2)异常终止连接,使用socket选项SO_LINGER来发送复位报文段;
3)处理半打开连接,服务器关闭连接,但是客户端网络故障没有收到结束报文段,客户端往半打开连接写入数据,服务器返回复位报文段。

3.7 TCP交互数据流

仅包含很少字节,要求高实时性,如telnet、ssh。
延迟确认:客户端针对服务器返回的数据所发送的确认报文段不携带任何数据,而服务器每次发送的确认报文段都包含它需要发送的应用程序数据,即它不马上确认上次收到的数据,而是在一段延迟时间后也看本端是否有数据需要发送,如果有,则和确认信息一起发出。因为服务器对客户请求处理得很快,所以它发送确认报文段的时候总是有数据一起发送。延迟确认可以减少发送TCP报文段的数量,而由于用户的输入速度明显慢于客户端程序的处理速度,所以客户端的确认报文段总是不携带任何应用程序数据。(TCP连接建立和断开时也可能发生)
Nagle算法:解决广域网下拥塞问题,要求一个TCP连接的通信双方在任意时刻都最多只能发送一个未被确认的TCP报文段,在该报文段的确认到达之前不能发送其他TCP报文段。另一方面,发送方在等待确认的同时收集本端需要发送的微量数据,井在确认到来时以一个TCP报文段将它们全部发出。这样就极大地减少了网络上的微小TCP报文段的数量。该算法的另一个优点在于其自适应性:确认到达得越快,数据也就发送得越快。

3.7 TCP成块数据流

长度通常为TCP报文段允许的最大数据长度,对传输效率要求高,如ftp。
当传输大量大块数据的时候,发送方会连续发送多个TCP报文段,接收方可以一次确认所有报文段。
发送方收到上一次确认后,能连续发送的TCP报文段数量取决于接收通告窗口和拥塞窗口。

3.8 带外数据

相对于普通数据(带内数据),不需要在发送缓冲区内排队,而是立即发送,telnet、ftp等远程非活跃程序会使用。
发送:设置 URG 标志,紧急指针指向数据流中带外数据的下一位置。
接收:根据紧急指针所指的位置确定带外数据的位置,并将它读入带外缓存,缓存只有1个字节。

3.9 TCP超时重传

TCP模块为每个TCP报文段都维护一个重传定时器,在报文段第一次发送时启动,超时未收到应答将重传并重置定时器。
每次重传超时时间都增加一倍(和TCP超时重连的策略相似)。在 n 次重传均失败的情况下,底层的IP和ARP开始接管,直到客户端放弃连接为止。n 与内核参数有关。

3.10 拥塞控制

提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。
Linux高性能服务器编程——ch3笔记_第7张图片
拥塞控制的最终受控变量是发送端向网络一次连续写入(收到其中第一个数据的确认前)的数据量,我们称为 SWND(发送窗口=min(CWND,RWND),CWND是拥塞窗口口状态变量)。不过,发送端最终以TCP报文段来发送数据,所以SWND限定发送端能连续发送的TCP报文段数量。SMSS指TCP报文段最大数据长度。
慢启动:CWND初始为IW,发送端每收到接收端的一个确认:
CWND+=min(N, SMSS),其中 N 是此次确认中包含的之前未被确认的字节数。目的是试探性地平滑增加。
拥塞避免:当CWND超过慢启动门限(ssthresh)时,进入拥塞避免阶段,CWND线性增加,方式:1)每个RTT时间内按照上式计算新的CWND,而不论该RTT时间内发送端收到多少确认;2)CWND+=SMSSSMSS/CWND。
快速重传快速恢复
1)当收到第3个重复的确认报文段时,ssthresh=max(FlightSize/2, 2
SMSS),然后立即重传丢失的报文段,CWND=ssthresh+3SMSS;
2)之后每次收到1个重复的确认时,CWND=CWND+SMSS,此时发送端可以发送新的 TCP 报文段(如果新的 CWND 允许的话)。
3)当收到新数据的确认时,设置 CWND=ssthresh,ssthresh是第一步的值。
上述是未检测到拥塞时的策略,拥塞发生时的依据和策略:
1)重传定时器溢出=>ssthresh=max(FlightSize/2, 2
SMSS)、令CWMD≤SMSS,其中FlightSize是已经发送但未收到确认的字节数。这样之后,CWMD将小于SMSS,那么也必然小于新的ssthresh=>慢启动和拥塞避免;
2)接收到重复的确认报文段(连续3次)(原因:TCP报文段丢失,或者接收端收到乱序 TCP报文段并重排之)=>快速重传和快速恢复。

你可能感兴趣的:(Linux服务器编程,服务器,linux,笔记)