Inside TCP/IP 读书记录

来源:互联网 发布:数据对比分析方法 编辑:程序博客网 时间:2024/05/22 03:21

把一些笔记转到blog上来,以免丢失。


中文RFC:www.cnpaf.net




-----------------------Chapter 1 概述----------------------------------


当前的以太网已经从总线型改为了(以集线器和交换机为核心的)星型网络。




TCP传给IP的数据单元称作TCP报文段或简称为TCP段(TCP segment、报文段)。IP传给网络接口层的数据单元称作IP数据报(IP datagram)。通过以太网传输的比特流称作帧(Frame)(数据帧)。
以太网数据帧的物理特性是其长度必须在46~1500字节之间。(数据部分)


大多数TCP/IP实现给临时端口分配1024~5000之间的端口号。大于5000的端口号是为其他服务器预留的(Internet上并不常用的服务)






---------------------Chapter 2 数据链路层-------------------------------
以太网的IP数据报封装格式是在RFC894中定义。IEEE802的IP数据报封装格式是在RFC1042中定义。
两种格式长度相同,但内部数据区结构不同。


以太网数据帧的最小长度为60字节,若包括以太网帧尾还要再加4字节为64字节。
以太网封装(rfc894)= 6byte目的地址 + 6byte源地址 + 2byte类型 + 46-1500byte数据 + 4byte以太网帧尾CRC。


Internet主机必须能够发送和接收RFC894(以太网)封装格式的分组。
硬件地址一般为48bit(6字节)。
ARP和RARP完成对32bit的IP地址和48bit的硬件地址进行映射。


PPP协议用于改进SLIP协议,最终会代替SLIP。
PPP用在串行链路上的通信,支持多协议(封包格式),带校验(CRC)。 PPP协议帧。


MTU:网络链路层特征。
以太网(1500字节)和IEEE 802(1492字节)对数据帧的最大长度有限制。这个特性称为MTU。
有时(以太网、s令牌环、802等)(可能)是物理特性,有时(PPP、SLIP)是逻辑限制(为得到足够快的响应时间)。
路径MTU:两台主机通信时,路径上的最小MTU。


以太网MSS为1460字节。802.3的MSS为1452字节。








-----------------------------------------Chapter 3 IP-----------------------------------------
IP层提供不可靠、无连接的服务。
1、不可靠:不保证IP数据报能成功到达目的地。如果网络层上的某个路由器缓冲区用完,IP会丢弃数据报,发ICMP消息给信源端。由上层(传输层或应用层)自己负责可靠性。
2、无连接:不维护任何关于后续数据报的状态信息。(无状态)。每个数据报的处理是相互独立的。(数据报的到达不是有序的)。




每个IP数据报都进行独立的路由选择??????




IP首部(基本字段共20byte) = 
4bit版本号 + 4bit首部长度(32bit的数目) + 8bit服务类型 + 16bit总长度
+ 16bit标识 + 3bit标志位 + 13bit片偏移
+ 8bit生存时间(TTL) + 8bit协议 + 16bit首部校验和
+ 32bit源IP地址
+ 32bit目的IP地址
+ 可选项(也算首部的内容)
+ 数据


首部长度:标示有几个32bit。所以首部最大可以有32bit*15=60字节。
TOS:包含最小时延、最大吞吐量、最高可靠性、最小费用。
总长度:整个IP数据报的字节数。结合首部长度,可以确定数据开始位置和长度。16bit决定了ip数据报最长为65535字节。
标识字段:发送序号???
TTL:设置数据报可以经过的最多路由器数。源主机设置,通常为32或64。每经过一个路由器减1。当值为0时,数据报丢弃,发送ICMP报文通知给源主机。


首部校验和:
只是对首部的校验和,不覆盖数据部分。 但ICMP、IGMP、tcp、udp首部中的校验和覆盖首部和数据部分。
校验和验证失败时,丢弃数据报,但不发送差错报文,由上层发现报文丢失并重传。


校验和算法:对每个16bit进行二进制反码求和。(发送方计算时,对校验和本身所在bit位,先置位0,再计算;接收方计算时,直接对所有16bit位计算,则结果应该全为1。)
ICMP、IGMP、UDP和TCP都采用相同的检验和算法。


IP中的可选字段:(作用)
记录路径(路由器IP)、时间戳(路由ip和时间)、源站选路(宽松、严格)、安全和处理限制(军用)
可选字段以32bit作为界限(IP首部长度以32bit整数倍计算)。




保留IP:
A类:10.0.0.0--10.255.255.255
     127.0.0.0--127.255.255.255
B类:172.16.0.0--172.31.255.255
C类:192.168.0.0--192.168.255.255


地址分类:
A类:0.0.0.0-127.255.255.255       0
B类:128.0.0.0-191.255.255.255 10
C类:192.0.0.0-223.255.255.255 110
D类:224.0.0.0-239.255.255.255 1110
E类:240.0.0.0-247.255.255.255 11110








----------IP路由选择---------


IP层既可以配置成路由器功能,也可以配置成主机功能。
大多数用户系统都可以配置成一个路由器。
IP层在内存中有一个路由表。


路由表项:
1、目的IP地址(主机地址或网络地址)
2、下一站路由器IP或直接连接的网络IP地址
3、标志位(其一指明目的IP地址是网络地址还是主机地址;其二,指明下一站路由器IP是路由器还是直接连接的网络接口)
4、网络接口


路由选择功能:(搜索路由表)
1、寻找与目的IP地址完全匹配的表目(网络号和主机号都匹配)。
2、寻找与目的网络号相匹配的表目。
3、寻找标为“默认”的表目。


如果以上路由过程都失败,则向生成数据报的引用程序返回一个“主机不可达”或“网络不可达”的ICMP差错报文。




为一个网络指定一个路由器,而不必为每个主机指定一个路由器。
Internet上的路由器的路由表中一般只有几千个表目。




子网编码:(因为给A类和B类网络地址的主机号分配了太大的空间。)
IP地址分为网络号和主机号,主机号又分为子网号和主机号。
使用子网号可以减少路由表目。(因为NIC上登记的IP地址才在Internet路由表中存在。nic中只能申请网络号。)




主机在引导时,需要配置IP地址。还需要知道哪些位是子网号和主机号。


子网掩码:
网络号和子网号bit为1,主机号bit为0。通常使用十六进制表示。比特掩码。


给定IP地址,通过IP地址类型、子网掩码,可以确定一个主机所在网络的结构。(网络号+子网号+主机号)。










网络字节序: (big endian)
以32bit数据为例,最高位在左边记为0bit,最低位在右边记为31bit。网络传输时,先传送高字节(0-7bit)。






-----------------------------------------Chapter 4 ARP-----------------------------------------


地址解析:实现IP地址和数据链路层地址的映射。
链路层地址只在同一广播域中有效。以太网中,只在同一IP网段有效。
ARP把IP地址映射为硬件地址(48bit)。


ARP是以太网环境下的地址转换机制。


以太网和局域网的关系????? 以太网只是一种局域网组网方式。还有令牌环网等。
ARP只是局域网内主机通信所需要的协议????
局域网内主机间的通信,不需要IP地址。????


ARP请求在其所在的局域网中广播,询问哪个主机有这个IP地址。但应答不是广播的,是直接回复给询问者的。
ARP应答包含IP地址和其硬件地址。


点对点链路不使用ARP。在设置链路时,把每一端的IP地址告知给内核。




ARP数据帧(42字节) = 以太网首部(14byte) + ARP请求(应答)(28byte);
以太网首部 = 以太网目的地址(6byte)+ 以太网源地址(6byte) + 帧类型(2byte)
ARP请求(应答) = 硬件类型(2byte)+ 协议类型(2byte)+ 硬件地址长度(1byte)+ 协议地址长度(1byte)+ 
op(2byte)+ 发送端以太网地址(6byte)+  发送端IP地址(4byte)+ 目的以太网地址(6byte)+ 目的IP地址(4byte)




只有ARP的应答收到后,(即得到目标的物理地址后),TCP的SYN报文才会发送。


一个数据报要发给远程主机(非局域网内部),是否也要ARP??? 中间链路上(源和目标的路由器之间)用ARP吗???


ARP高速缓存的有效时间为20min。不完整的表项(目标主机不存在)有效时间为3min。
系统收到arp请求(或发送arp应答)时,会把请求端的IP和硬件地址放入缓存。
当收到免费ARP请求时,会自动更新到缓存。




ARP代理(委托ARP):ARP请求从一个网络发往另一个网络,连接这两个网络的主机就可以回答该ARP请求,就是ARP代理。
代理ARP的使用一般是使用在没有配置默认网关和路由策略的网络上的。 
如果主机配置了默认网关,若ARP请求查询的对象在局域网外,则该查询任务交给网关处理。
代理ARP只是解决跨局域网地址查询的一种方法。使用默认网关是主流方法。


主机只会向其子网内的主机发ARP请求(局域网广播)。
ARP请求以广播的方式发出,被路由器限制在局域网之内。(路由器默认不转发广播)。
主机没有配置路由信息的情况下,才会把对外网IP的查询在子网内广播。
当对外网IP的查询进行广播时,如果路由器支持代理ARP,并且目标IP在路由器的路由表中,则路由器以目标IP和自己的MAC地址回复该查询。
如果要查询的IP地址在主机(网络接口)的子网内,则向子网内发ARP请求的广播。如果要查询的IP地址不在其子网内的,则去查路由表,而不会再发ARP广播。
如果主机没有配置路由信息(默认路由、默认网关),则无法分清哪些IP是外网的,所有MAC地址查询都会进行ARP请求。




免费ARP: 查询自己IP的ARP请求。一般发生在系统引导过程中。




主动端每发送一个IP数据报都要发一个ARP请求并等待应答吗??? 不是。在局域网内部发送数据时才需要arp。


路由器之间会传递ARP请求吗 ?????




------------------------------------------Chapter 5 RARP--------------------------------------


RARP使用于无盘系统引导阶段。


RARP协议和ARP协议的格式相同。帧类型、op等字段不同。


RARP请求以广播方式发送,RARP应答以单播方式发送。


RARP服务器的功能由用户进程提供,不是内核的TCP\IP实现的一部分。
RARP服务器的实现与系统相关。






------------------------------------------Chapter 6 ICMP---------------------------------------


ICMP通常被认为是IP层的一部分。


ICMP数据报 = IP头部 + ICMP报文
ICMP报文 = ICMP报文头 + 内容
ICMP报文头(必含的8个字节) = 8bit类型 + 8bit代码 + 16bit校验和(必选) + 32bit类型相关数据(未用时必须为0)(但对设置不可分片的IP数据报产生的不可达差错报文中可以把路由器的出口MTU写在低16位中。)
但ICMP报文头里只有前4个字节是相同的。


ICMP的校验和是必须的。
icmp报文分:查询报文和差错报文。
差错报文包括:产生差错的IP数据报的首部(包含任何选项,不一定20字节)、产生差错的IP数据报内容字段的前8个字节(对tcp是源端口+目标端+发送序列号;对udp是源端口+目标端口+udp长度+校验和)。


路径MTU发现:设置不可分片标记时,在需要分片的路由器位置产生不可达差错报文,会把路由器的出口MTU写在ICMP第二个四节的低16上。(ICMP不可达差错报文通常使用8个字节的ICMP报文头。)


对IP数据报,路由器缓存用完,则IP层丢弃该数据报,然后发送ICMP数据报给信源端。








不产生ICMP差错报文的情况:
1、icmp差错报文本身。
2、目标地址为广播、组播地址ip数据报。
3、用在链路层广播的数据报。
4、不是第一个分片的ip数据报。
5、源地址不是单个主机地址的数据报。(如零地址、环回地址、广播地址、多播地址)。




以太网首部为14字节。
广播的接收者包括发送者本身。
ICMP报文是在主机之间交换的,不用端口号。




握手的过程会有icmp差错报文吗???
不可达差错对tcp和udp都有效吗???


用户进程如何接收到ICMP差错报文???
生成端口不可达差错是否为必须???


UDP协议时,对socket端口进行connect,可以接收ICMP差错报文。???


ICMP报文需要内核处理的,那么内核直接处理。(也可能发送ICMP报文的拷贝给用户进程。)
ICMP报文需要用户进程处理的,会传送给所有内核中登记的用户进程。












-----------------------------------------Chapter 9 IP选路--------------------------------------












------------------------------------------Chapter 11 UDP---------------------------------------


UDP首部只有8个字节。(tcp有20字节)
UDP头 = 16bit源端口 + 16bit目标端口
+ 16bitUDP长度(头和数据) + 16bitUDP校验和


tcp端口号和udp端口号是相互独立的。???只是说tcp数据包只会传给tcp,udp数据包只会传给udp。在ip层就区分开了。
根据业务的需要,两种协议也会选择同一个端口号。


udp的校验和是可选项;tcp的校验和是必选项。
tcp和upd的校验和都覆盖其头部和数据。IP首部的校验和只覆盖IP首部。
如果接收端发现校验和(IP层、UDP层)有错,就直接丢弃数据报而不产生差错报文。
如果发送的校验和为0,则说明发送端没有计算校验和。如果有,接收端必须进行校验。




UDP数据报在链路上传输时,有被路由器等设备修改的可能。所以需要校验和。




UDP数据报和TCP段都包含一个12字节的伪首部。是为计算校验和而设置。 算长度时算在哪里了???只是为了计算校验和,不传送。


校验和:16bit字(反码)相加。所以,无法区分出数据报中16bit字交互位置。


数据链路层的CRC检验和tcp或udp校验和,都是简单的校验和,不能检测出所有可能的差错。




udp数据报有分片的需求。tcp段通常没有分片需求(mss小于等于mtu)。
在路径的任何路由器上都可能出现对IP数据报的分片。
IP数据报被分片后,只有到达最终目的地才进行组装。
分片和组装发生在IP层,对上层(tcp、udp)透明。


发送一个大于MTU的数据报,但设置“不分片”标志,会收到ICMP差错报文。(应用层如何知道???)


一个UDP数据报被分片后,如有一个分片(IP数据报)丢失,就需要重传整个UDP数据报。
IP层本身没有超时重传机制。而且起始端也不知道中间路由器如何分段的。(TCP有超时和重传,UDP没有。)


UDP数据报被分片后,UDP头部只出现在第一个分片中。


IP数据报指IP层端到端的传输单元(分片前和重新组装后)。(因为分组和重装都是在IP层完成,对上层透明。)
分组是在IP层和数据链路层之间传递的数据单元。
一个分组可是一个完整的IP数据报,也可以是IP数据报的一个分片。
分组也是以一个IP数据报的形式传送的。??? 第一个分片是结构完整(ip头+udp头+数据)的IP数据报,其余的是缺少UDP头部的IP数据报。(如果是tcp,则缺少tcp头部。)




ICMP不可达差错(需要分片):
可用来进行路径MTU发现。


采用UDP的路径MTU发现:
IP定时器周期性(30s或更大间隔)把DF置1,以查看路径MTU是否增大了。




ICMP组装超时差错:在目标端重新组装数据时出错或超时。


UDP的接收端在接到一个分片后,会启动一个定时器(30s或60s),如果在定时器超时时,数据报的分片没有全部到达,则丢掉这些数据报分片。但许多实现不产生ICMP组装超时差错。所以,一个数据报太大而造成分片太多时会增加无法送达的风险。


tcpdump: frag 74942:512@1024+) 
74942代表IP数据报序号;512表示当前的分片的长度;1024代表当前分片对原始IP数据报首位置的偏移量;+表示还有更多分片。


UDP数据报长度:应用程序数据一般限制为512字节。
应用程序读取数据报发生截断时,有些实现(Berkeley)丢弃剩余部分,有些实现(SVR4)不丢弃可继续读。


ICMP原站抑制差错:
当接收端(包括路由器)的接收缓冲满时,可能(不是必须)会发送ICMP原站抑制(source quench)差错。
新的RFC认为路由器不应该产生原站抑制差错报文。




IP_RECVDSTADDR


每个UDP端口都有一个输入队列。


1、应用程序不知道输入队列溢出。
2、udp丢弃数据报时,不告知客户端。(无icmp差错报文)。
3、UDP输出队列是FIFO的。






一台机器上的多个服务器(进程)可以使用不同的IP和相同的端口号,但后面(第二个开始)启动的服务器必须指定SO_REUSEADDR告知系统。
一台机器上的多个服务器(进程)要使用相同的IP和相同的端口号,则需要同时指定SO_REUSEADDR和SO_REUSEPORT(从第一个启动的服务器开始)。(只用于UDP多播???)(有人测试没有使用SO_REUSEPORT也没影响。???)


一个进程绑定不同的ip,相同的端口,到多个socket上,需指定SO_REUSEADDR。




SO_REUSEADDR可以用在以下四种情况下。
(摘自《Unix网络编程》卷一,即UNPv1)
1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。
2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。
3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。
4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。








------------------------Chapter 15 TFTP:简单文件传输协议----------------------


TFTP是一个简单的协议,适合于只读存储器,仅用于无盘系统进行系统引导。它只使用几种报文格式,是一种停止等待协议。


最初用于引导无盘系统。
基于UDP。要处理分组丢失和分组重复。 


支持netascii和octet模式文件。默认使用netascii。




5种TFTP报文格式:
1、操作码(1=RRQ/2=WRQ)(2byte)+ 文件名(nbyte)+ 0(1byte)+ 模式(nbyte)+ 0(1byte)
2、操作码(3=date)(2byte)+ 块编号(2byte)+ 数据(0-512byte)
3、操作码(4=ACK)(2byte)+ 块编号(2byte)
4、操作码(5=error)(2byte)+ 差错码(2byte)+ 差错信息(nbyte)+ 0(1byte)


停止等待协议。
特别之处: 服务器收读写请求报文是在TFTP的熟知端口(69),而回复数据是使用新的端口。






------------------------Chapter 17 TCP:传输控制协议---------------------------


tcp提供可靠性的方式:
1、应用数据被tcp分隔成合适大小的块,传输过程中数据报长度保持不变(与udp不同)。
2、超时重发。
3、收到数据后,发确认。(但不立即发确认,推迟200ms后确认)。
4、带校验和。(强制的。udp的校验和是可选的。)
5、TCP会对收到的数据重新排序,以便把有序的数据交给应用层。 IP数据报可能无序到达,所以TCP报文段也可能无序到达。
6、TCP会丢弃重复报文段。(IP数据报会重复)。
7、TCP提供流量控制机制。






TCP首部 = 源Port(16bit)+ 目标Port(16bit)
+ 发送序号(32bit)
+ 确认序号(32bit)
+ 首部长度(4bit)+保留位(6bit)+ 标志位(URG + ACK + PSH + RST + SYN + FIN)(各1bit) + 窗口大小(16bit)
+ 校验和(16bit)+ 紧急指针(16bit)
+ 选项(一般不存在)


TCP报文段 = TCP首部(20字节) + TCP数据
IP数据报 = IP首部(20字节) + TCP报文段






TCP段中的发送序号:tcp连接对持续发送字节流的每个字节进行计数,其值标记tcp报文段第一个数据字节在整个字节流中的序号。 
TCP报文段的序号还是字节流中字节的序号??? 字节序号
syn的初始序号(ISN)怎么算???  (系统初始化为1,每4ms加1,每个连接的可获取到的ISN不同。每次建立一个连接ISN加64000。) 


TCP段中的确认序号:是接收端给发送端的,指明接收端期望下一个收到的报文段的序号。(发送序号 + 1)


TCP传输是全双工的。两个方向上的发送序号独立。


TCP的确认序号,不能选择确认,只能按序确认。而且不能对错误的报文段进行否认。


MSS(Maximum Segment Size)在可选字段中。连接方在通信的第一个报文段(为建立连接而设置SYN标志的那个段)中指明MSS。






--------------------------------------Chapter 18 TCP连接的建立和终止----------------------------------------


nastygram 圣诞树分组


主动连接(打开)端发SYN,被动连接(打开)端发SYN+ACK。主动端再发一个ACK。完成连接。


主动断开方发FIN+ACK,被动断开方发ACK,完成一个方向的连接断开。另一个方向的断开过程相同。
为何断开连接时,被动断开端要先ACK,而没有使用FIN+ACK一个报文段完成确认和断开??? tcp连接是全双工的,所以每个方向必须单独地进行关闭。可能此时被动断开端还有需要向主动断开端发送数据,所以不能在收到fin后同时关闭写连接。




握手(连接建立)过程只需不到0.01s。
握手时,syn包超时,再次发syn包的间隔会越来越大。(如第一次为5.8s,第二次为24s,然后48s后超时。非精准数据)
大多数伯克利系统将建立一个新连接的最长时间限制为75s。(TCP连接超时的定时器为500ms。)




socket api close() 是同步过程吗??? 
close()只能断开一个方向的连接吗??? 断开两个方向上的连接。 
shutdown()可以指明只断开一个方向上的连接。另一个方向上的连接还可以继续发送数据。
close()是指明了不接收对端再写数据了,以及对端写缓冲区里的数据都要被丢弃吗??? ???


FIN的ACK包、SYN的ACK包都是系统自己产生,不需要程序员处理。
SYN_RCVD状态时,收到RST,会再回到LISTEN状态。




MSS(Maximum Segment Size)表示TCP传往另一端的最大块数据的长度。不包括tcp头和ip头。
MSS只能出现在SYN报文段中。如果一方不接受来自另一方的MSS值,则MSS就定为默认值536字节。(MTU值 - IP头长度 - TCP头长度)
以太网MSS为1460字节。802.3的MSS为1452字节。BSD系统要求MSS为512的倍数。
握手时,两个主机只知道自己出口的MTU,并不知道路径上的MTU。所以如果路径上MTU小于两个主机自己报的MTU(MSS+40),仍然会出现重新分段。 ???是的。
mss只能在SYN包中指定。
mss不包含ip头和tcp头大小。mss = 外出接口上的MTU - IP头 -TCP头。
如果目的IP地址为非本地,则mss通常选默认值536。
每个peer知道自己外出接口上的MTU,但不知道路径上的MTU,若路径上的mtu小,仍可能出现分包现象。




MSL:tcp报文段的最大生存时间。通常为2分钟。
TTL:IP数据报的最大生存时间。使用跳数,不是定时器。


TIME_WAIT:用于防止fin的最后一个ACK(主动关闭方发出的ack)丢失重传时出现混淆。只有主动关闭的一方才会进入这个状态。
同时,会导致这个连接(五元组)在2msl内不可用。伯克利tcp,强制在2msl内,本地端口不能再被使用。








RST:


UDP协议发包时,对端port不可用,会产生ICMP报文。 TCP协议连接时,对端port不可用,会产生RST包。


Socket API 通过“linger on close”选项(SO_LINGER)提供连接异常关闭的能力,即发送RST包,(丢弃缓冲区里的待发送数据)。


接收到RST报文段的一端,直接断开连接,通知应用层复位,不进行确认(ACK)。


如果so_linger设置了超时时间,对非阻塞的fd,closesocket是否会阻塞????






TCP连接使用keepalive选项,可以帮助发现半打开(half-open)(比如一端突然断电、拔掉网线重启程序)的连接。


对于半打开连接发出的数据报,TCP的处理原则是接收方以复位(RST包)应答。




同时打开:
每一方必须发送syn,且这些syn必须传递给对方。(这需要每一方使用对方知道的地址和端口)。


同时关闭:
两端各发一个fin,都进入fin_wait_1状态。收到对端的fin后,发ack,并进入closing状态。各自收到ack后,进入time_wait状态。




只有处于LISTEN状态的进程能接收SYN报文段。而只有处于ESTABLISHED状态的进程能接收数据报文段。




backlog:积压值。即连接队列的长度(BSD上与长度不一致),取值0-5,通常使用5。
已被TCP接受(已完成三次握手),而等待被应用层接受的最大连接数。 与最多连接数、并发处理的客户数无关。
被tcp接受的连接,加入连接队列;应用层接受该连接后,从连接队列中取出。




主动打开是通过connect完成的吗? connect返回,表示三次握手完成吗? 这时候被动打开方的应用层是否已经接受了连接(即应用层是否知道新连接)。
三次握手完成,connect就返回。此时,可能应用层还未接受连接(accept),但connect发起端已经可以发送数据了。
对客户端而言,三次握手完成,就表示主动打开成功。






当服务器握手完成,服务器的应用层没有接收(还不知道)这个新连接时,服务器的tcp仅将收到的数据放入缓冲区。


如果服务器的连接队列满,服务器将不再处理syn包,也不发回rst包。客户端的主动打开会超时。
如果服务器程序未启动,客户端会收到rst。


TCP服务器无法使客户进程的主动打开失效。因为三次握手完成后,客户端的主动打开就算成功了。而服务器端是在应用层拿到这个新连接后才能知道客户端的ip和port,这时候连接已经被服务器的应用层接受了,要想拒绝就只能关闭了(发fin or rst)。




-------------------------------------------Chapter 19 TCP的交互数据流------------------------------------------------


捎带ack的发送方式:
等待200ms(内核计时,和接收时间无关)再发送ack,尽量把ack和下一个包合并(如放在push的数据包中)。
经受时延的ack。
Nagle算法:
tcp连接上最多只有一个未被确认的分组,在收到ack包之前,累积数据,收到ack包之后,发送缓冲区使用一个tcp报文段,把累积的数据发送过去。是累积发送的一种方式。
TCP_NODELAY可以关闭Nagle算法。(设置PUSH标志也是这样的作用。)




-------------------------------------------Chapter 20 TCP的成块数据流------------------------------------------------


窗口更新:
当接收端缓冲区满后,通告给发送端停止发送;但等接收端缓冲区内的数据被读出(全部?不需全部,只要被应用层部分读出)后,接收端会再给发送端发ack包通告滑动窗口张开。
许多TCP实现在窗口大小增加了两个最大报文段长度(2MSS)或者最大可能窗口的50%时发送这个窗口更新。


对以太网而言,默认的4096字节并不是最理想的大小,将两个缓存增加到16384个字节可以增加约40%左右的吞吐量。


4.4BSD默认发送和接收缓冲区大小为8k或16k。




慢启动算法需要在客户端增加一个拥塞窗口(cwnd)。 一次连续发送拥塞窗口大小(初始化为1mss)的数据包,每确认(ack)一个,窗口大小增加一个,从而实现指数增长。
拥塞窗口是发送方使用的流量控制;通告窗口是接收方使用的流量控制。


使用带宽时延乘积衡量网络管道的容量。


紧急方式发送的数据不是带外数据。(ie:被通告窗口为0时,可以使用紧急方式发送数据给接收端。)


使用紧急报文来指明紧急数据的开始(紧急状态开始)。紧急指针指向紧急数据结束位置(紧急数据的最后一位)。数据里(部分)带有紧急数据,则需要指明URG字段为1;一旦不在该包数据区间里,则URG置0,紧急状态结束。 
紧急数据必须放置在报文数据的开始位置???




tcp为应用层提供的是有序数据,如果出现丢包,应用层无法读到失序的数据?????丢包则后续数据未被确认。








-------------------------------------------Chapter 21 TCP的超时与重传-------------------------------------------------




指数退避(exponential backoff)


如果正常连接被断开网线,数据会多次重传,并最终在大约9分钟时放弃(RST链路)。对大多数实现,这个时间是不可调整的。


RTO(Retransmission TimeOut): 重传超时时间。在RTT的基础上进行平滑算法所得。RTT估计器。上限为64s。
RTT(Round Trip Time)


重传多义性问题: 
Karn算法:在一个超时和重传发生时,在重传数据的确认达到之前,不能更新RTT估计器。


快速重传:
伯克利TCP对收到的重复ACK进行计数,当收到3个重复的ack,则认为该报文段丢失并重传这个报文段。
快速重传:
当一个序号的push包被确认(ack)后,又连续收到3个确认(ack)该序号的包,则认为以该序号开始的包丢失,立即重传这一个包。这就是Jacobson的快速重传算法。
在重传后,不需要等待接收方确认重传,发送方继续正常的发送数据。


慢启动算法是在一个连接上发起数据流的方法;拥塞避免算法是一种处理丢失分组的方法。是两个目的不同的独立算法。在实际中,两个算法通常一起实现。
两个算法需要对每一个连接维持两个变量:一个拥塞窗口(cwnd)和一个慢启动门限(ssthresh)。
算法工作过程:
1、对于一个给定连接,初始化cwnd为1mss,ssthresh为65535字节。
2、发送数据量不能超过min(cwnd, 通告窗口大小)(即为当前发送窗口)。
3、当拥塞发生时(超时或收到重复ack),ssthresh设置为当前发送窗口大小的一半(但最少为2mss)。如果是超时引起拥塞,cwnd设置为1mss(慢启动)。
4、当收到新的ack时,增加cwnd大小。增加方法:if(cwnd <= ssthresh) 进行慢启动;else 进行拥塞避免。


拥塞避免:
是发送方使用的流量控制;通告窗口是接收方使用的流量控制。
在cwnd达到ssthresh之前,每收到一个确认(ack),cwnd增加1,同时多发送一个push。这就是慢启动阶段。
当cwnd达到ssthresh大小时,每收到一个确认(ack),cwnd增加1/cwnd,(即一个rtt时间,cwnd增加1)。这就是拥塞避免阶段。




(超时重传和丢包重传):


一、TCP认为网络拥塞的主要依据是它重传了一个报文段。TCP对每一个报文段都有一个定时器,称为重传定时器(RTO),当RTO超时且还没有得到数据确认,那么TCP就会对该报文段进行重传,当发生超时时,那么出现拥塞的可能性就很大,某个报文段可能在网络中某处丢失,并且后续的报文段也没有了消息,在这种情况下,TCP反应比较“强烈”:
1.把ssthresh降低为cwnd值的一半
2.把cwnd重新设置为1       (慢启动)
3.重新进入慢启动过程。
二、其实TCP还有一种情况会进行重传:那就是收到3个相同的ACK。TCP在收到乱序到达包时就会立即发送ACK,TCP利用3个相同的ACK来判定数据包的丢失,此时进行快速重传,快速重传做的事情有:
1.把ssthresh设置为cwnd的一半
2.把cwnd再设置为ssthresh的值(具体实现有些为ssthresh+3)  (快速恢复)
3.重新进入拥塞避免阶段。




注意,冗余ACK是不能捎带的。




拥塞避免是发送方使用的流量控制,通告窗口是接收方进行的流量控制。
4.3bsd reno上慢启动总是被执行。


拥塞避免时,慢启动窗口加数增长。每经过一个RTT,cwnd加1。 一个RTT如何确定???从一个包发出,到收到该包的ack,这个时间段为rtt。


慢启动过程中,当cwnd达到ssthresh的大小时,慢启动结束,同时进入拥塞避免。拥塞避免过程中,cwnd线性增长(一个rtt,加1)到发送超时,cwnd置1,ssthresh减为当前发送窗口一半(最小为2mss)。这时cwnd < ssthresh,再次进入慢启动过程。重复前面的过程。


ssthresh(慢启动阈值),表明估计拥塞窗口达到这个值时可能要出现拥塞了。所以此后就加法增大cwnd。




分组丢失的两种标识: 
1、发生超时。
2、收到重复的确认。




如果由于报文段的重新排序而发送重复的ack,则重复ack个数只可能有1-2个。 ???


快速重传:
当出现拥塞时(3个重复ack),不需等待发送超时,直接重传丢失的报文段,这就是快速重传。同时也进入拥塞避免。


快速恢复:
在出现拥塞之后,再收到重复ack,说明接收端收到了新的失序数据,并成功收下了。此时,cwnd线性增加(每收到一个重复ack,增加1)。这样丢失的报文段之后发送的报文段就能继续有效。一旦快速重传发送的报文段被确认(收到ack),那么从丢失报文到第一个重复ack之间的报文段都有效。这就是快速恢复。




ICMP差错:
TCP能够遇到的最常见的ICMP差错就是源站抑制、主机不可达和网络不可达。
当收到原站抑制时,引起cwnd置为1,进入慢启动。
当发生主机不可达或网络不可达时,不必关闭连接。通常需要重新查找路由。




发生超时重传时,tcp可能不是发送最初的分组,而包含了后续数据,重新分组,以尽可能大(1mss内)的分组把数据发出去。






--------------------------------------------Chapter 22 TCP的坚持定时器------------------------------------------------


接收ack的一方不对ack报文进行确认。 所以,用于窗口更新的ack报文丢失,会造成一直等待而连接终止。所以需要窗口探查。


窗口探查:发送方周期性地向接收方查询窗口是否张开(变大)。


当收到通告窗口为0时,启动坚持定时器。窗口打开后,坚持定时器关闭。
坚持定时器使用TCP指数退避。超时时间指数增大,直至60s。




窗口探查时,如果窗口没有打开,接收方会回ack包,但不确认用于探查的一字节数据;
一旦出现窗口打开,是否会确认用于探查的这一个字节。??? 不会了。
窗口探查包有特殊标记吗???




糊涂窗口综合症(Silly Window Syndrome):由于对方通告的窗口太小(小于1mss),或者发送方也不等待达到一个mss的窗口,而发出不满长度的报文段。
避免措施:(双方或任一方)
1、接收方不通告小窗口。至少一个mss。
2、发送方满足下列条件之一才发送数据:a)可以发送一个满长度的报文。b)可以发送至少是通告窗口一半大小的报文段。c)可以发送任何数据并且不希望接收ACK,或禁止了Nagle算法。


通告了一个大于1mss窗口(n),但发送方只用了1mss(m),而剩余的不足1mss(n-m),此时,接收方仍通告(n-m)大小的窗口。因为滑动窗口的右边沿通常不能左移(窗口收缩)。






-----------------------------------------Chapter 23 TCP的保活定时器-----------------------------------------


一个tcp连接建立后,即使双方没有发送数据,连接也可以保持很久(几个月)。


保活功能可以帮助服务器发现半打开的连接。(客户端直接掉线、断电等造成没有发close)。


保活定时器周期为2小时。一个连接在2小时内没有动作,服务器就发送探查报文段。
1、如果客户端已经崩溃或重启中,则服务器无法收到响应,服务器会尝试10次,每次间隔75s。10次无法收到响应,则认为客户端已经断开。
2、如果客户端已重启完成,则服务器的探查会收到一个RST报文段的回应,服务器终止这个连接。
3、如果路由链路出现问题(如线路断开、路由器关闭),保活端会收到ICMP差错报文(软差错),保活会尝试10次,间隔75s。




探查报文如何发现客户端已经重启过了?????


------------------------------------------Chapter 24 TCP的未来和性能---------------------------------------
 
TCP在高速网络环境中,有缺陷。


长肥管道(long fat pipe):具有很大带宽时延乘积的网络。长肥网络。




路径MTU发现:
IP首部设置DF,如果该IP数据报长度超过MTU,那么路由器返回ICMP不可达差错(不能分片差错)。




TCP的路径MTU发现:在连接建立时, TCP使用本端和对端MSS的最小值作为起始的报文段大小。路径MTU发现不允许TCP超过对端声明的MSS。如果对端没有指定一个MSS,则默认为536。


大分组、小分组:
分组不一定是越大越好。














----------------------------------------------Chapter 27 FTP-------------------------------------------------




FTP最早的设计是用于两台不同的主机,这两个主机可能运行在不同的操作系统下、使用不同的文件结构、并可能使用不同字符集。


采用两个tcp连接传输一个文件: 
1、控制连接。(最大限度减小延迟)。
2、数据连接。(最大限度提高吞吐量)。




通常由Unix实现的FTP 客户和服务器把我们的选择限制如下:
• 类型:ASCI I或图像。
• 格式控制:只允许非打印。
• 结构:只允许文件结构。
• 传输方式:只允许流方式。









































0 0
原创粉丝点击