TCP/IP详解学习笔记(5)-IP选路,动态选路,和一些细节html
1.静态IP选路算法
1.1.一个简单的路由表数据库
选路是IP层最重要的一个功能之一。前面的部分已经简单的讲过路由器是经过何种规则来根据IP数据包的IP地址来选择路由。这里就不重复了。首先来看看一个简单的系统路由表。编程
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.11.0 * 255.255.255.0 U 0 0 0 eth0
169.254.0.0 * 255.255.0.0 U 0 0 0 eth0
default 192.168.11.1 0.0.0.0 UG 0 0 0 eth0缓存
对于一个给定的路由器,能够打印出五种不一样的flag。服务器
1. U代表该路由可用。网络
2. G代表该路由是到一个网关。若是没有这个标志,说明和Destination是直连的,而相应的Gateway应该直接给出Destination的地址。数据结构
3. H代表该路由是到一个主机,若是没有该标志,说明Destination是一个网络,换句话说Destination就应该写成一个网络号和子网号的组合,而不包括主机号(主机号码处为0),例如 192.168.11.0并发
4. D代表该路由是为重定向报文建立的dom
5. M该路由已经被重定向报文修改
U没啥可说的,G说明这是一个网关,若是你要发数据给Destination,IP头应该写Destination的IP地址,而数据链路层的MAC地址就应该是GateWay的Mac地址了;反之,若是没有G标志,那么数据链路层和IP层的地址应该是对应的。H说明了Destination的性质,若是是H的,则说明该地址是一个完整的地址,既有网络号又有主机号,那么再匹配的时候就既要匹配网络号,又要匹配主机号;反之,Destination就表明一个网络,在匹配的时候只要匹配一下网络号就能够了。
这样,IP选路的方式就能够更加具体化了。以下
1. 首先用IP地址来匹配那些带H标志的DestinationIP地址。
2. 若是1失败就匹配那些网络地址。
3. 若是2失败就发送到Default网关
顺便提一下那个GenMask(还记得子网掩码么),它指定了目的地址的子网号,例如第一条的子网就是11。
1.2.其余有关路由表的知识
通常,咱们在配置好一个网络接口的时候,一个路由就被直接建立好了。固然咱们也能够手动添加路由。用route add命令就能够了。
而当一个IP包在某一个路由器的时候发现没有路由可走,那么该路由器就会给源主机发送“主机不可达”或者“网络不可达”的ICMP包来报错。
注意,通常的操做系统默认是没有路由功能的,这须要本身配置。这些历史缘由就不细说了,
1.3.ICMP的IP重定向报文和路由发现报文
当IP包在某一个地方转向的时候,都回给发送IP报的源主机一个ICMP重定向报文,而源主机就能够利用这个信息来更新本身的路由表,这样,随着网络通讯的逐渐增多,路由表也就愈来愈完备,数据转发的速度也会愈来愈快。咱们须要注意的是:
1. 重定向报文只能由路由器发出。
2. 重定向报文为主机所用,而不是为路由器所用。
在主机引导的时候,通常会发送在网内广播一个路由请求的ICMP报文,而多个路由器则会回应一个路由通告报文。并且,路由其自己不按期的在网络内发布路由通告报文,这样,根据这些报文,每个主机都会有机会创建本身的路由表而实现网络通讯。路由器在一份通告报文中能够通告多个地址,而且给出每个地址的优先等级,这个优先等级是该IP做为默认路由的等级,至于怎么算的就不深究了。
路由器通常会在450-600秒的时间间隔内发布一次通告,而一个给定的通告报文的寿命是30分钟。而主机在引导的时候会每三秒发送一次请求报文,一旦接受到一个有效的通告报文,就中止发送请求报文。
在TCP/IP详解编写的时候,只有Solaris2.x支持这两种报文,大多数系统还不支持这两种报文。(后面还会讲到一些有用的路由报文)
动态选路协议
前面的选路方法叫作静态选路,简要地说就是在配置接口的时候,以默认的方式生成路由表项。并经过route来增长表项,或者经过ICMP报文来更新表项(一般在默认方式出错的状况下)。而若是上诉三种方法都不能知足,那么咱们就使用动态选路。
动态选路协议是用于动态选路的重要组成部分,可是他们只是使用在路由器之间,相邻路由器之间互相通讯。系统(路有选择程序)选择比较合适的路有放到核心路由表中,而后系统就能够根据这个核心路有表找到最合适的网路。也就是说,动态选路是在系统核心网络外部进行的,它只是用一些选路的策略影响路由表,而不会影响到最后经过路由表选择路由的那一部分。选路协议有一大类经常使用的叫作内部网关协议(IGP),而在IGP中,RIP就是其中最重要的协议。一种新的IGP协议叫作开放最短路经优先(OSPF)协议,其意在取代RIP。另外一种最先用在网路骨干网上的IGP协议--HELLO,如今已经不用了。
现在,任何支持动态选路的路由器都必须同时支持OSPF和RIP,还能够选择性的支持其余的IGP协议。
2.1.Unix选路程序
Unix系统上面一般都有路由守护程序--routed。还有一个叫作gate。gate所支持的协议要比routed多,routed只是支持RIPv1版本。而gate则支持RIPv一、v2,BGPv1 等等。
2.1.RIP:选路信息协议
它的定义能够在RFC1058内找到,这种协议使用UDP做为载体(也就是UDP的上层协议)。咱们最关心的就是RIP其中的一个段,叫作度量的段,这是一个以hop做为计数器(就是以走过多少路由为计数器)的段(IP协议里面也有一个TTL不是么)。这个度量段将最终影响到路由表的创建。参考图:
通常说来routed要承担以下的工做:
1. 给每个已知的路由器发送rip请求报文,要求其余路由器给出完整的路由表。这种报文的命令字段为1,地址字段为0,度量地段为16(至关于无穷大)。
2. 接受请求,若是接收到刚才的那个请求,就把本身的完整的路由表交给请求者。若是没有,就处理IP请求表项,把表项中本身有的部分添上跳数,没有的部分添上16。而后发给请求者。
3. 接受回应。更新本身的路由表。使用hop数小的规则。
4. 按期更新路由表,通常是30s(真频繁)给相邻的路有启发一次本身的路由表。这种形式可使广播形式的。
这个协议看起来会工做的很好,可是,这里面其实有不少隐藏的忧患,好比说RIP没有子网的概念,好比说环路的危险。并且hop数的上限也限制了网络的大小。
所以,出现了不少RIPv1的替代品,好比说RIPv2,好比说OSPF。他们都是经过某种策略来影响路由表,因此就不说了。
TCP/IP详解学习笔记(6)-UDP协议
1.UDP简要介绍
UDP是传输层协议,和TCP协议处于一个分层中,可是与TCP协议不一样,UDP协议并不提供超时重传,出错重传等功能,也就是说其是不可靠的协议。
2.UDP协议头
2.1.UDP端口号
因为不少软件须要用到UDP协议,因此UDP协议必须经过某个标志用以区分不一样的程序所须要的数据包。端口号的功能就在于此,例如某一个UDP程序A在系统中注册了3000端口,那么,之后从外面传进来的目的端口号为3000的UDP包都会交给该程序。端口号理论上能够有2^16这么多。由于它的长度是16个bit
2.2.UDP检验和
这是一个可选的选项,并非全部的系统都对UDP数据包加以检验和数据(相对TCP协议的必须来讲),可是RFC中标准要求,发送端应该计算检验和。
UDP检验和覆盖UDP协议头和数据,这和IP的检验和是不一样的,IP协议的检验和只是覆盖IP数据头,并不覆盖全部的数据。UDP和TCP都包含一个伪首部,这是为了计算检验和而摄制的。伪首部甚至还包含IP地址这样的IP协议里面都有的信息,目的是让UDP两次检查数据是否已经正确到达目的地。若是发送端没有打开检验和选项,而接收端计算检验和有差错,那么UDP数据将会被悄悄的丢掉(不保证送达),而不产生任何差错报文。
2.3.UDP长度
UDP能够很长很长,能够有65535字节那么长。可是通常网络在传送的时候,一次通常传送不了那么长的协议(涉及到MTU的问题),就只好对数据分片,固然,这些是对UDP等上级协议透明的,UDP不须要关心IP协议层对数据如何分片,下一个章节将会稍微讨论一些分片的策略。
3.IP分片
IP在从上层接到数据之后,要根据IP地址来判断从那个接口发送数据(经过选路),并进行MTU的查询,若是数据大小超过MTU就进行数据分片。数据的分片是对上层和下层透明,而数据也只是到达目的地还会被从新组装,不过不用担忧,IP层提供了足够的信息进行数据的再组装。
在IP头里面,16bit识别号惟一记录了一个IP包的ID,具备同一个ID的IP片将会被从新组装;而13位片偏移则记录了某IP片相对整个包的位置;而这两个表示中间的3bit标志则标示着该分片后面是否还有新的分片。这三个标示就组成了IP分片的全部信息,接受方就能够利用这些信息对IP数据进行从新组织(就算是后面的分片比前面的分片先到,这些信息也是足够了)。
由于分片技术在网络上被常常的使用,因此伪造IP分片包进行流氓攻击的软件和人也就层出不穷。
能够用Trancdroute程序来进行简单的MTU侦测。请参看教材。
3.UDP和ARP之间的交互式用
这是不常被人注意到的一个细节,这是针对一些系统地实现来讲的。当ARP缓存仍是空的时候。UDP在被发送以前必定要发送一个ARP请求来得到目的主机的MAC地址,若是这个UDP的数据包足够大,大到IP层必定要对其进行分片的时候,想象中,该UDP数据包的第一个分片会发出一个ARP查询请求,全部的分片都辉等到这个查询完成之后再发送。事实上是这样吗?
结果是,某些系统会让每个分片都发送一个ARP查询,全部的分片都在等待,可是接受到第一个回应的时候,主机却只发送了最后一个数据片而抛弃了其余,这实在是让人匪夷所思。这样,由于分片的数据不能被及时组装,接受主机将会在一段时间内将永远没法组装的IP数据包抛弃,而且发送组装超时的ICMP报文(其实不少系统不产生这个差错),以保证接受主机本身的接收端缓存不被那些永远得不到组装的分片充满。
4.ICMP源站抑制差错
当目标主机的处理速度赶不上数据接收的速度,由于接受主机的IP层缓存会被占满,因此主机就会发出一个“我受不了”的一个ICMP报文。
5.UDP服务器设计
UDP协议的某些特性将会影响咱们的服务器程序设计,大体总结以下:
1. 关于客户IP和地址:服务器必须有根据客户IP地址和端口号判断数据包是否合法的能力(这彷佛要求每个服务器都要具有)
2. 关于目的地址:服务器必需要有过滤广播地址的能力。
3. 关于数据输入:一般服务器系统的每个端口号都会和一块输入缓冲区对应,进来的输入根据先来后到的原则等待服务器的处理,因此不免会出现缓冲区溢出的问题,这种状况下,UDP数据包可能会被丢弃,而应用服务器程序自己并不知道这个问题。
4. 服务器应该限制本地IP地址,就是说它应该能够把本身绑定到某一个网络接口的某一个端口上。
1.单播,多播,广播的介绍
1.1.单播(unicast)
单播是说,对特定的主机进行数据传送。例如给某一个主机发送IP数据包。这时候,数据链路层给出的数据头里面是很是具体的目的地址,对于以太网来 说,就是网卡的MAC地址(不是FF-FF-FF-FF-FF-FF这样的地址)。如今的具备路由功能的主机应该能够将单播数据定向转发,而目的主机的网 络接口则能够过滤掉和本身MAC地址不一致的数据。
1.2.广播(unicast)
广播是主机针对某一个网络上的全部主机发送数据包。这个网络多是网络,多是子网,还多是全部的子网。若是是网络,例如A类网址的广播就是 netid.255.255.255,若是是子网,则是netid.netid.subnetid.255;若是是全部的子网(B类IP)则是则是 netid.netid.255.255。广播所用的MAC地址FF-FF-FF-FF-FF-FF。网络内全部的主机都会收到这个广播数据,网卡只要把 MAC地址为FF-FF-FF-FF-FF-FF的数据交给内核就能够了。通常说来ARP,或者路由协议RIP应该是以广播的形式播发的。
1.3.多播(multicast)
能够说广播是多播的特例,多播就是给一组特定的主机(多播组)发送数据,这样,数据的播发范围会小一些(实际上播发的范围一点也没有变小),多播的MAC地址是最高字节的低位为一,例如01-00-00-00-00-00。多播组的地址是D类IP,规定是224.0.0.0-239.255.255.255。
虽然多播比较特殊,可是究其原理,多播的数据仍是要经过数据链路层进行MAC地址绑定而后进行发送。因此一个以太网卡在绑定了一个多播IP地址以后,必 定还要绑定一个多播的MAC地址,才能使得其能够像单播那样工做。这个多播的IP和多播MAC地址有一个对应的算法,在书的p133到p134之间。能够看到 这个对应不是一一对应的,主机仍是要对多播数据进行过滤。
我的的见解:广播和多播的性质是同样的,路由器会把数据放到局域网里面,而后网卡对这些数据进行过滤,只拿到本身打算要的数据,好比本身感兴趣的多 播数据,本身感兴趣的组播数据。当一个主机运行了一个处理某一个多播IP的进程的时候,这个进程会给网卡绑定一个虚拟的多播mac地址,并作出来一个多播 ip。这样,网卡就会让带有这个多播mac地址的数据进来,从而实现通讯,而那些没有监听这些数据的主机就会把这些数据过滤掉,换句话说,多播,是让主机 的内核轻松了,而网卡,对不起,您就累点吧。
一些文章也印证了这种想法,最明显的就是局域网监听的原理、实现与防范
2.一些验证性实验
这些实验并非很复杂,咱们只是要ping一下通常的ip和一个广播地址。首先我ping一下本身所在的子网的某一台主机:
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time=1ms TTL=255
能够看到,机器返回的是一台主机的回应结果,进而推测,若是我ping一个广播地址呢?结果以下
Reply from 192.168.11.9: bytes=32 time=1ms TTL=255
Reply from 192.168.11.174: bytes=32 time<1ms TTL=64
Reply from 192.168.11.174: bytes=32 time<1ms TTL=64
Reply from 192.168.11.174: bytes=32 time<1ms TTL=64
Reply from 192.168.11.218: bytes=32 time<1ms TTL=64
Reply from 192.168.11.174: bytes=32 time<1ms TTL=64
能够看到,ping返回了一些随机的ip的结果,这些ip都是与主机在同一子网内的ip。咱们能够看到,广播其实是给处于子网内的全部ip发信。
再来一个多播的例子,可是要实现这个多播并不容易,由于我不知道网络内有多少个多播组,就只好利用几个特殊的多播地址来验证了。
对于多播地址,有几个特殊的多播地址被占用,他们是
1. 224.0.0.1--该子网内全部的系统组。
2. 224.0.0.2--该子网内全部的路由器。
3. 224.0.1.1--网络实现协议NTP专用IP。
4. 224.0.0.9--RIPv2专用IP
因此只要ping这几个IP,就应该能获得一些结果,好比说我ping 224.0.0.2。
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
咱们能够看到,这回ping只返回了一个ip的回应。而这个就是个人网关的地址,这也验证了224.0.0.2是全部路由器的多播(组播)地址
3.IGMP协议
IGMP的做用在于,让其余全部须要知道本身处于哪一个多播组的主机和路由器知道本身的状态。通常多播路由器根本不须要知道某一个多播组里面有多少个主机,而只要知道本身的子网内还有没有处于某个多播组的主机就能够了。只要某一个多播组还有一台主机,多播路由器就会把数据传输出去,这样,接受方就会经过网卡过滤功能来获得本身想要的数据。为了知道多播组的信息,多播路由器须要定时的发送IGMP查询,IGMP的格式能够看书,各个多播组里面的主机要根据查询来回复本身的状态。路由器来决定有几个多播组,本身要对某一个多播组发送什么样的数据。
这种查询回应数据报的TTL通常是1,并且就算是出错也不产生ICMP差错(不必)。
TCP/IP详解学习笔记(9)-TCP协议概述
终于看到了TCP协议,这是TCP/IP详解里面最重要也是最精彩的部分,要花大力气来读。前面的TFTP和BOOTP都是一些简单的协议,就不写笔记了,写起来也没啥东西。
TCP和UDP处在同一层---运输层,可是TCP和UDP最不一样的地方是,TCP提供了一种可靠的数据传输服务,TCP是面向链接的,也就是说,利用TCP通讯的两台主机首先要经历一个“拨打电话”的过程,等到通讯准备结束才开始传输数据,最后结束通话。因此TCP要比UDP可靠的多,UDP是把数据直接发出去,而无论对方是否是在收信,就算是UDP没法送达,也不会产生ICMP差错报文,这一经时重申了不少遍了。
把TCP保证可靠性的简单工做原理摘抄以下
· 应用数据被分割成TCP认为最适合发送的数据块。这和UDP彻底不一样,应用程序产生的 数据报长度将保持不变。由TCP传递给IP的信息单位称为报文段或段( segment)(参见图1 - 7)。在1 8.4节咱们将看到TCP如何肯定报文段的长度。
· 当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。若是不能 及时收到一个确认,将重发这个报文段。在第21章咱们将了解TCP协议中自适应的超时 及重传策略。
· 当TCP收到发自TCP链接另外一端的数据,它将发送一个确认。这个确认不是当即发送,一般将推迟几分之一秒,这将在1 9.3节讨论。
· TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输 过程当中的任何变化。若是收到段的检验和有差错, T P将丢弃这个报文段和不确认收到此报文段(但愿发端超时并重发)。
· 既然TCP报文段做为IP数据报来传输,而IP数据报的到达可能会失序,所以TCP报文段 的到达也可能会失序。若是必要, TCP将对收到的数据进行从新排序,将收到的数据以正确的顺序交给应用层。
· TCP还能提供流量控制。TCP链接的每一方都有固定大小的缓冲空间。TCP的接收端只容许另外一端发送接收端缓冲区所能接纳的数据。这将防止较快主机导致较慢主机的缓冲区溢出。
从这段话中能够看到,TCP中保持可靠性的方式就是超时重发,这是有道理的,虽然TCP也能够用各类各样的ICMP报文来处理这些,可是这也不是可靠的,最可靠的方式就是只要不获得确认,就从新发送数据报,直到获得对方的确认为止。
TCP的首部和UDP首部同样,都有发送端口号和接收端口号。可是显然,TCP的首部信息要比UDP的多,能够看到,TCP协议提供了发送和确认所须要的全部必要的信息。这在P171-173有详细地介绍。能够想象一个TCP数据的发送应该是以下的一个过程。
· 双方创建链接
· 发送方给接受方TCP数据报,而后等待对方的确认TCP数据报,若是没有,就从新发,若是有,就发送下一个数据报。
· 接受方等待发送方的数据报,若是获得数据报并检验无误,就发送ACK(确认)数据报,并等待下一个TCP数据报的到来。直到接收到FIN(发送完成数据报)
· 停止链接
能够想见,为了创建一个TCP链接,系统可能会创建一个新的进程(最差也是一个线程),来进行数据的传送
前面已经提到了访问一台机器要靠IP地址和MAC地址,其中,MAC地址能够经过ARP协议获得,因此这对用户是透明的,可是IP地址就不行,不管如何用户都须要用一个指定的IP来访问一台计算机,而IP地址又很是很差记,因而就出现了DNS系统
1.DNS系统介绍
DNS的全称是Domain Name System。它负责把FQDN(就是以"."分隔结尾的名字)翻译成一个IP。最初的DNS系统使用的是一个巨大的hosts.txt文件(很吃惊,用 这个就好使了?),但是一段时间之后,开发这就不得不用数据库来代替hosts.txt文件,最终发展到了如今的分布式数据库。
从书中的143页能够看到,DNS系统是一个巨大的树,最上方有一个无名树根,下一层是arpa,com,edu,gov,int,mil,us, cn。等等,其中arpa,是域名反解析树的顶端;而com,edu,等域名原本只用在美国(这就是技术特权啊),可是如今几乎全世界通用;而us, cn,等叫作国家域。这个树里面的域名并非统一管理的,网络信息中心(NIS)负责分配顶级域合委派其余制定地区域的受权机构。
一个独立管理的DNS子树叫作zone,最多见的区域就是二级域名,好比说.com.cn。咱们还能够把这个二级域名给划分红更小的区域,好比说sina.com.cn。
DNS系统是一个分布式的数据库,当一个数据库发现本身并无某查询所须要的数据的时候,它将把查询转发出去,而转发的目的地一般是根服务器,根服 务器从上至下层层转发查询,直到找到目标为止。DNS还有一个特色就是使用高速缓存,DNS把查询过的数据缓存在某处,以便于下次查询时使用。
2.DNS协议
DNS报文定义了一个既能够查询也能够响应的报文格式。具体格式能够看P145页。对各个字段简单解释以下
1. 最前面的16个bit惟一的标示了问题号码,用于查询端区别本身的查询。
2. 紧接着的16个bit又能够作进一步的细分,标示了报文的性质和一些细节,好比说是查询报文仍是响应报文,须要递归查询与否(通常服务器都支持递归查询,并且不须要任何设置,BIND就是这样)
3. 查询问题后面有查询类型,包括A,NS,CNAME,PTR,HINFO,MX,若是熟悉BIND的话,就知道在zong的配置文件里面,每一条记录都记载了各自的类型,好比A就是IP地址,NS就是名字服务器。
4. 响应报文能够回复多个IP,也就是说,域名能够和多个IP地址对应,而且有不少CNAME。
3.反向查询
正向查询指的是经过域名获得IP的查询,而反向查询就是经过IP获得域名。例如用host命令,host ip就能够获得服务器的域名,host domainName 就获得IP。
稍微知道一点数据结构的人都能意识到,在正向查询的域里面作反向查询,其作法只有遍历整个数据集合----对于DNS来讲,那就是遍历整个数据库, 这将带来巨大的负担,因此DNS采起了另外一种方法,使用另外一棵子树来维护IP-〉域名的对应表。这个子树的根节点是in-addr.arpa,而一个IP例如192.168.11.2)所具备的DNS地址就是 2.11.168.192.in-addr.arpa(ip倒置)。在DNS系统里面,一个反向地址对应一个PTR纪录(对应A纪录),因此反向查询又叫 作指针(PTR)查询。
4.其余问题的讨论
4.1.DNS服务器高速缓存
BIND9默认是做为一个高速缓存服务器,其将全部的查询都转交到根服务器去,而后获得结果并放在本地的缓冲区,以加快查询速度。若是有兴趣能够安装一个BIND9来尝试一下。而本身定义的zone则能够规定其在缓存中的时间,通常是1天(就是配置文件中的1D)。
4.2.用UDP仍是TCP
DNS服务器支持TCP和UDP两种协议的查询方式,并且端口都是53。而大多数的查询都是UDP查询的,通常须要TCP查询的有两种状况:
1. 当查询数据多大以致于产生了数据截断(TC标志为1),这时,须要利用TCP的分片能力来进行数据传输(看TCP的相关章节)。
2. 当主(master)服务器和辅(slave)服务器之间通讯,辅服务器要拿到主服务器的zone信息的时候。
完
TCP是一个面向链接的协议,因此在链接双方发送数据以前,都须要首先创建一条链接。这和前面讲到的协议彻底不一样。前面讲的全部协议都只是发送数据而已,大多数都不关心发送的数据是否是送到,UDP尤为明显,从编程的角度来讲,UDP编程也要简单的多----UDP都不用考虑数据分片。
书中用telnet登录退出来解释TCP协议链接的创建和停止的过程,能够看到,TCP链接的创建能够简单的称为三次握手,而链接的停止则能够叫作四次握手。
1.链接的创建
在创建链接的时候,客户端首先向服务器申请打开某一个端口(用SYN段等于1的TCP报文),而后服务器端发回一个ACK报文通知客户端请求报文收到,客户端收到确认报文之后再次发出确认报文确认刚才服务器端发出的确认报文(绕口么),至此,链接的创建完成。这就叫作三次握手。若是打算让双方都作好准备的话,必定要发送三次报文,并且只须要三次报文就能够了。
能够想见,若是再加上TCP的超时重传机制,那么TCP就彻底能够保证一个数据包被送到目的地。
2.结束链接
TCP有一个特别的概念叫作half-close,这个概念是说,TCP的链接是全双工(能够同时发送和接收)链接,所以在关闭链接的时候,必须关闭传和送两个方向上的链接。客户机给服务器一个FIN为1的TCP报文,而后服务器返回给客户端一个确认ACK报文,而且发送一个FIN报文,当客户机回复ACK报文后(四次握手),链接就结束了。
3.最大报文长度
在创建链接的时候,通讯的双方要互相确认对方的最大报文长度(MSS),以便通讯。通常这个SYN长度是MTU减去固定IP首部和TCP首部长度。对于一个以太网,通常能够达到1460字节。固然若是对于非本地的IP,这个MSS可能就只有536字节,并且,若是中间的传输网络的MSS更佳的小的话,这个值还会变得更小。
4.TCP的状态迁移图
书P182页给出了TCP的状态图,这是一个看起来比较复杂的状态迁移图,由于它包含了两个部分---服务器的状态迁移和客户端的状态迁移,若是从某一个角度出发来看这个图,就会清晰许多,这里面的服务器和客户端都不是绝对的,发送数据的就是客户端,接受数据的就是服务器。
4.1.客户端应用程序的状态迁移图
客户端的状态能够用以下的流程来表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
以上流程是在程序正常的状况下应该有的流程,从书中的图中能够看到,在创建链接时,当客户端收到SYN报文的ACK之后,客户端就打开了数据交互地链接。而结束链接则一般是客户端主动结束的,客户端结束应用程序之后,须要经历FIN_WAIT_1,FIN_WAIT_2等状态,这些状态的迁移就是前面提到的结束链接的四次握手。
4.2.服务器的状态迁移图
服务器的状态能够用以下的流程来表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
在创建链接的时候,服务器端是在第三次握手以后才进入数据交互状态,而关闭链接则是在关闭链接的第二次握手之后(注意不是第四次)。而关闭之后还要等待客户端给出最后的ACK包才能进入初始的状态。
4.3.其余状态迁移
书中的图还有一些其余的状态迁移,这些状态迁移针对服务器和客户端两方面的总结以下
1. LISTEN->SYN_SENT,对于这个解释就很简单了,服务器有时候也要打开链接的嘛。
2. SYN_SENT->SYN收到,服务器和客户端在SYN_SENT状态下若是收到SYN数据报,则都须要发送SYN的ACK数据报并把本身的状态调整到SYN收到状态,准备进入ESTABLISHED
3. SYN_SENT->CLOSED,在发送超时的状况下,会返回到CLOSED状态。
4. SYN_收到->LISTEN,若是受到RST包,会返回到LISTEN状态。
5. SYN_收到->FIN_WAIT_1,这个迁移是说,能够不用到ESTABLISHED状态,而能够直接跳转到FIN_WAIT_1状态并等待关闭。
4.4.2MSL等待状态
书中给的图里面,有一个TIME_WAIT等待状态,这个状态又叫作2MSL状态,说的是在TIME_WAIT2发送了最后一个ACK数据报之后,要进入TIME_WAIT状态,这个状态是防止最后一次握手的数据报没有传送到对方那里而准备的(注意这不是四次握手,这是第四次握手的保险状态)。这个状态在很大程度上保证了双方均可以正常结束,可是,问题也来了。
因为插口的2MSL状态(插口是IP和端口对的意思,socket),使得应用程序在2MSL时间内是没法再次使用同一个插口的,对于客户程序还好一些,可是对于服务程序,例如httpd,它老是要使用同一个端口来进行服务,而在2MSL时间内,启动httpd就会出现错误(插口被使用)。为了不这个错误,服务器给出了一个平静时间的概念,这是说在2MSL时间内,虽然能够从新启动服务器,可是这个服务器仍是要平静的等待2MSL时间的过去才能进行下一次链接。
4.5.FIN_WAIT_2状态
这就是著名的半关闭的状态了,这是在关闭链接时,客户端和服务器两次握手以后的状态。在这个状态下,应用程序还有接受数据的能力,可是已经没法发送数据,可是也有一种多是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态。
5.RST,同时打开和同时关闭
RST是另外一种关闭链接的方式,应用程序应该能够判断RST包的真实性,便是否为异常停止。而同时打开和同时关闭则是两种特殊的TCP状态,发生的几率很小。
6.TCP服务器设计
前面曾经讲述过UDP的服务器设计,能够发现UDP的服务器彻底不须要所谓的并发机制,它只要创建一个数据输入队列就能够。可是TCP不一样,TCP服务器对于每个链接都须要创建一个独立的进程(或者是轻量级的,线程),来保证对话的独立性。因此TCP服务器是并发的。并且TCP还须要配备一个呼入链接请求队列(UDP服务器也一样不须要),来为每个链接请求创建对话进程,这也就是为何各类TCP服务器都有一个最大链接数的缘由。而根据源主机的IP和端口号码,服务器能够很轻松的区别出不一样的会话,来进行数据的分发。
掌握本章的状态迁移图才是学习本章的关键。
TCP/IP详解学习笔记(11)-TCP交互数据流,成块数据流
目前创建在TCP协议上的网络协议特别多,有telnet,ssh,有ftp,有http等等。这些协议又能够根据数据吞吐量来大体分红两大类:(1)交互数据类型,例如telnet,ssh,这种类型的协议在大多数状况下只是作小流量的数据交换,好比说按一下键盘,回显一些文字等等。(2)数据成块类型,例如ftp,这种类型的协议要求TCP能尽可能的运载数据,把数据的吞吐量作到最大,并尽量的提升效率。针对这两种状况,TCP给出了两种不一样的策略来进行数据传输。
1.TCP的交互数据流
对于交互性要求比较高的应用,TCP给出两个策略来提升发送效率和减低网络负担:(1)捎带ACK。(2)Nagle算法(一次尽可能多的发数据)。一般,在网络速度很快的状况下,好比用lo接口进行telnet通讯,当按下字母键并要求回显的时候,客户端和服务器将经历 发送按键数据->服务器发送按键数据的ack -> 服务器端发送回显数据->客户端发送回显数据的ACK的过程,而其中的数据流量将是40bit + 41bit+41bit+40bit = 162bit,若是在广域网里面,这种小分组的TCP流量将会形成很大的网络负担。
1.1.捎带ACK的发送方式
这个策略是说,当主机收到远程主机的TCP数据报以后,一般不立刻发送ACK数据报,而是等上一个短暂的时间,若是这段时间里面主机还有发送到远程主机的TCP数据报,那么就把这个ACK数据报“捎带”着发送出去,把原本两个TCP数据报整合成一个发送。通常的,这个时间是200ms。能够明显地看到这个策略能够把TCP数据报的利用率提升不少。
1.2.Nagle算法
上过bbs的人应该都会有感觉,就是在网络慢的时候发贴,有时键入一串字符串之后,通过一段时间,客户端“发疯”同样忽然回显出不少内容,就好像数据一会儿传过来了同样,这就是Nagle算法的做用。
Nagle算法是说,当主机A给主机B发送了一个TCP数据报并进入等待主机B的ACK数据报的状态时,TCP的输出缓冲区里面只能有一个TCP数据报,而且,这个数据报不断地收集后来的数据,整合成一个大的数据报,等到B主机的ACK包一到,就把这些数据“一股脑”的发送出去。虽然这样的描述有些不许确,但还算形象和易于理解,咱们一样能够体会到这个策略对于低减网络负担的好处。
在编写插口程序的时候,能够经过TCP_NODELAY来关闭这个算法。而且,使用这个算法看状况的,好比基于TCP的X窗口协议,若是处理鼠标事件时仍是用这个算法,那么“延迟”可就很是大了。
2.TCP的成块数据流
对于FTP这样对于数据吞吐量有较高要求的要求,将老是但愿每次尽可能多的发送数据到对方主机,就算是有点“延迟”也无所谓。TCP也提供了一整套的策略来支持这样的需求。TCP协议中有16个bit表示“窗口”的大小,这是这些策略的核心。
2.1.传输数据时ACK的问题
在解释滑动窗口前,须要看看ACK的应答策略,通常来讲,发送端发送一个TCP数据报,那么接收端就应该发送一个ACK数据报。可是事实上却不是这样,发送端将会连续发送数据尽可能填满接受方的缓冲区,而接受方对这些数据只要发送一个ACK报文来回应就能够了,这就是ACK的累积特性,这个特性大大减小了发送端和接收端的负担。
2.2.滑动窗口
滑动窗口本质上是描述接受方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算本身最多能发送多长的数据。若是发送方收到接受方的窗口大小为0的TCP数据报,那么发送方将中止发送数据,等到接受方发送窗口大小不为0的数据报的到来。书中的P211和P212很好的解释了这一点。
关于滑动窗口协议,书上还介绍了三个术语,分别是:
1. 窗口合拢:当窗口从左边向右边靠近的时候,这种现象发生在数据被发送和确认的时候。
2. 窗口张开:当窗口的右边沿向右边移动的时候,这种现象发生在接受端处理了数据之后。
3. 窗口收缩:当窗口的右边沿向左边移动的时候,这种现象不常发生。
TCP就是用这个窗口,慢慢的从数据的左边移动到右边,把处于窗口范围内的数据发送出去(但不用发送全部,只是处于窗口内的数据能够发送。)。这就是窗口的意义。图20-6解释了这一点。窗口的大小是能够经过socket来制定的,4096并非最理想的窗口大小,而16384则可使吞吐量大大的增长。
2.3.数据拥塞
上面的策略用于局域网内传输还能够,可是用在广域网中就可能会出现问题,最大的问题就是当传输时出现了瓶颈(好比说必定要通过一个slip低速链路)所产生的大量数据堵塞问题(拥塞),为了解决这个问题,TCP发送方须要确认链接双方的线路的数据最大吞吐量是多少。这,就是所谓的拥塞窗口。
拥塞窗口的原理很简单,TCP发送方首先发送一个数据报,而后等待对方的回应,获得回应后就把这个窗口的大小加倍,而后连续发送两个数据报,等到对方回应之后,再把这个窗口加倍(先是2的指数倍,到必定程度后就变成现行增加,这就是所谓的慢启动),发送更多的数据报,直到出现超时错误,这样,发送端就了解到了通讯双方的线路承载能力,也就肯定了拥塞窗口的大小,发送方就用这个拥塞窗口的大小发送数据。要观察这个现象是很是容易的,咱们通常在下载数据的时候,速度都是慢慢“冲起来的”
以上就是TCP数据传输的大体流程,虽然并不细致,可是足以描述TCP的工做原理,重点是TCP的流量控制原理,滑动窗口,拥塞窗口,ACK累计确认等知识点。
TCP/IP详解学习笔记(12)-TCP的超时与重传
超时重传是TCP协议保证数据可靠性的另外一个重要机制,其原理是在发送某一个数据之后就开启一个计时器,在必定时间内若是没有获得发送的数据报的ACK报文,那么就从新发送数据,直到发送成功为止。
1.超时
超时时间的计算是超时的核心部分,TCP要求这个算法能大体估计出当前的网络情况,虽然这确实很困难。要求精确的缘由有两个:(1)定时长久会形成网络利用率不高。(2)定时过短会形成屡次重传,使得网络阻塞。因此,书中给出了一套经验公式,和其余的保证计时器准确的措施。
1.1.递推公式概说
最先的TCP曾经用了一个很是简单的公式来估计当前网络的情况,以下
R<-aR+(1-a)M
RTP=Rb
其中a是一个经验系数为0.1,b一般为2。注意,这是经验,没有推导过程,这个数值是能够被修改的。这个公式是说用旧的RTT(R)和新的RTT(M)综合到一块儿来考虑新的RTT(R)的大小。可是,咱们又看到,这种估计在网络变化很大的状况下彻底不能作出“灵敏的反应”(Jacoboson说的,不是偶说的,呵呵),因而就有下面的修正公式:
Err=M-A
A<-A+gErr
D<-D+h(|Err|-D)
RTO=A+4D
具体的解释请看书的228页,这个递推公式甚至把方差这种统计概念也使用了进来,使得误差更加的小。并且,必需要指出的是,这两组公式更新,都是在数据成功传输的状况下才进行,在发生数据从新传输的状况下,并不使用上面的公式进行网络估计,理由很简单,由于程序已经不在正常状态下了,估计出来的数据也是没有意义的。
1.2.RTO的初始化
RTO的初始化是由公式决定的,例如最初的公式,初始的值应该是1。而修正公式,初始RTO应该是A+4D。
1.3.RTO的更新
当数据正常传输的状况下,咱们就会用上面的公式来更新各个数据,并重开定时器,来保证下一个数据被顺利传输。要注意的是:重传的状况下,RTO不用上面的公式计算,而采用一种叫作“指数退避”的方式。例如:当RTO为1S的状况下,发生了数据重传,咱们就用RTO=2S的定时器来从新传输数据,下一次用4S。一直增长到64S为止。
1.4.估计器的初始化
在这里,SYN用的估计器初始化彷佛和传输用的估计器不同(我也没有把握)造个人理解,在修正公式中,SYN的状况下,A初始化为0,D初始化为3S。
而在获得传输第一个数据的ACK的时候,应该按照下面的公式进行初始化:
A=M+0.5
D=A/2
1.5.估计器的更新
和上面的讨论差很少,就是在正常状况下,用上面的公式计算,在重传的状况下,不更新估计器的各类参数。缘由仍是由于估计不许确。
1.6.Karn算法
这不算是一个算法,这应该是一个策略,说的就是更新RTO和估计器的值的时机选择问题,1.3.和1.5.所说得更新时机就是Karn算法。
1.7.计时器的使用
两句话:
1. 一个链接中,有且仅有一个测量定时器被使用。也就是说,若是TCP连续发出3组数据,只有一组数据会被测量。
2. ACK数据报不会被测量,缘由很简单,没有ACK的ACK回应能够供结束定时器测量。
2.重传
有了超时就要有重传,可是就算是重传也是有策略的,而不是将数据简单的发送。
2.1.重传时发送数据的大小
前面曾经提到过,数据在传输的时候不能只使用一个窗口协议,咱们还须要有一个拥塞窗口来控制数据的流量,使得数据不会一会儿都跑到网路中引发“拥塞”。也曾经提到过,拥塞窗口最初使用指数增加的速度来增长自身的窗口,直到发生超时重传,再进行一次微调。可是没有提到,如何进行微调,拥塞避免算法和慢启动门限就是为此而生。
所谓的慢启动门限就是说,当拥塞窗口超过这个门限的时候,就使用拥塞避免算法,而在门限之内就采用慢启动算法。因此这个标准才叫作门限,一般,拥塞窗口记作cwnd,慢启动门限记作ssthresh。下面咱们来看看拥塞避免和慢启动是怎么一块儿工做的
算法概要(直接从书中拷贝)
1. 对一个给定的链接,初始化cwnd为1个报文段,ssthresh为65535个字节。
2. TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小。拥塞避免是发送方使用 的流量控制,而通告窗口则是接收方进行的流量控制。前者是发送方感觉到的网络拥塞的估 计,然后者则与接收方在该链接上的可用缓存大小有关。
3. 当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半(cwnd 和接收方通告窗口大小的最小值,但最少为2个报文段)。此外,若是是超时引发了拥塞,则 cwnd被设置为1个报文段(这就是慢启动)。
4. 当新的数据被对方确认时,就增长cwnd,但增长的方法依赖于咱们是否正在进行慢启 动或拥塞避免。若是cwnd小于或等于ssthresh,则正在进行慢启动,不然正在进行拥塞避免。 慢启动一直持续到咱们回到当拥塞发生时所处位置的半时候才中止(由于咱们记录了在步骤2 中给咱们制造麻烦的窗口大小的一半),而后转为执行拥塞避免。
补充上面的拥塞避免公式在P238页。这整个的流程让我联想到开车换档的过程。
2.2.快速重传和快速恢复算法
这是数据丢包的状况下给出的一种修补机制。通常来讲,重传发生在超时以后,可是若是发送端接受到3个以上的重复ACK的状况下,就应该意识到,数据丢了,须要从新传递。这个机制是不须要等到重传定时器溢出的,因此叫作快速重传,而从新传递之后,由于走的不是慢启动而是拥塞避免算法,因此这又叫作快速恢复算法。流程以下:
1. 当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半。重传丢失的 报文段。设置cwnd为ssthresh加上3倍的报文段大小。
2. 每次收到另外一个重复的ACK时, cwnd增长1个报文段大小并发送1个分组(若是新的 cwnd容许发送)。
3. 当下一个确认新数据的ACK到达时,设置cwnd为ssthresh(在第1步中设置的值)。这个 ACK应该是在进行重传后的一个往返时间内对步骤1中重传的确认。另外,这个ACK也应该 是对丢失的分组和收到的第1个重复的ACK之间的全部中间报文段的确认。这一步采用的是拥 塞避免,由于当分组丢失时咱们将当前的速率减半。
2.3.ICMP会引发从新传递么?
答案是:不会,TCP会坚持用本身的定时器,可是TCP会保留下ICMP的错误而且通知用户。
2.4.从新分组
TCP为了提升本身的效率,容许再从新传输的时候,只要传输包含重传数据报文的报文就能够,而不用只重传须要传输的报文。
TCP/IP详解学习笔记(13)-TCP坚持定时器,TCP保活定时器
TCP一共有四个主要的定时器,前面已经讲到了一个--超时定时器--是TCP里面最复杂的一个,另外的三个是:
1. 坚持定时器
2. 保活定时器
3. 2MSL定时器
其中坚持定时器用于防止通告窗口为0之后双方互相等待死锁的状况;而保活定时器则用于处理半开放链接
1.坚持定时器
坚持定时器的原理是简单的,当TCP服务器收到了客户端的0滑动窗口报文的时候,就启动一个定时器来计时,并在定时器溢出的时候向向客户端查询窗口是否已经增大,若是获得非零的窗口就从新开始发送数据,若是获得0窗口就再开一个新的定时器准备下一次查询。经过观察能够得知,TCP的坚持定时器使用1,2,4,8,16……64秒这样的普通指数退避序列来做为每一次的溢出时间。
糊涂窗口综合症
TCP的窗口协议,会引发一种一般叫作糊涂窗口综合症的问题,具体表现为,当客户端通告一个小的非零窗口时,服务器马上发送小数据给客户端并充满其缓冲区,一来二去就会让网络中充满小TCP数据报,从而影响网络利用率。对于发送方和接收端的这种糊涂行为。TCP给出了一些建议(或者是规定)。
1. 接收方不通告小窗口。一般的算法是接收方不通告一个比当前窗口大的窗口(能够为0),
除非窗口能够增长一个报文段大小(也就是将要接收的MSS)或者能够增长接收方缓存空间
的一半,不论实际有多少。
2. 发送方避免出现糊涂窗口综合症的措施是只有如下条件之一知足时才发送数据: ( a )可
以发送一个满长度的报文段; ( b )能够发送至少是接收方通告窗口大小一半的报文段; ( c )能够
发送任何数据而且不但愿接收ACK(也就是说,咱们没有还未被确认的数据)或者该链接上
不能使用Nagle算法。
ok,如今咱们回忆一下,能够发现TCP的不少规定都是为了在一次传送中发送尽可能多的数据,例如捎带ACK数据报文的策略,Nagle算法,重传时发送包含原数据报文的策略,等等。
2.保活定时器
保活定时器更加的简单,还记得FTP或者Http服务器都有Sesstion Time机制么?由于TCP是面向链接的,因此就会出现只链接不传送数据的“半开放链接”,服务器固然要检测到这种链接而且在某些状况下释放这种链接,这就是保活定时器的做用。其时限根据服务器的实现不一样而不通。另外要提到的是,当其中一端若是崩溃并从新启动的状况下,若是收到该端“前生”的保活探察,则要发送一个RST数据报文帮助另外一端结束链接。
摘自:http://www.cnblogs.com/fengzanfeng/articles/1339347.html
后续参考:http://blog.csdn.net/goodboy1881/article/details/762079