为何会有TCP/IP协议linux
在世界上各地,各类各样的电脑运行着各自不一样的操做系统为你们服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别。就好像圣经中上帝打乱了各地人的口音,让他们没法合做同样。计算机使用者意识到,计算机只是单兵做战并不会发挥太大的做用。只有把它们联合起来,电脑才会发挥出它最大的潜力。因而人们就千方百计的用电线把电脑链接到了一块儿。git
可是简单的连到一块儿是远远不够的,就好像语言不一样的两我的互相见了面,彻底不能交流信息。于是他们须要定义一些共通的东西来进行交流,TCP/IP就是为此而生。TCP/IP不是一个协议,而是一个协议族的统称。里面包括了IP协议,IMCP协议,TCP协议,以及咱们更加熟悉的http、ftp、pop3协议等等。电脑有了这些,就好像学会了外语同样,就能够和其余的计算机终端作自由的交流了。算法
提到协议分层,咱们很容易联想到ISO-OSI的七层协议经典架构,可是TCP/IP协议族的结构则稍有不一样。如图所示数据库
TCP/IP协议族按照层次由上到下,层层包装。最上面的就是应用层了,这里面有http,ftp,等等咱们熟悉的协议。而第二层则是传输层,著名的TCP和UDP协议就在这个层次(不要告诉我你没用过udp玩星际)。第三层是网络层,IP协议就在这里,它负责对数据加上IP地址和其余的数据(后面会讲到)以肯定传输的目标。第四层是叫数据链路层,这个层次为待传送的数据加入一个以太网协议头,并进行CRC编码,为最后的数据传输作准备。再往下则是硬件层次了,负责网络的传输,这个层次的定义包括网线的制式,网卡的定义等等(这些咱们就不用关心了,咱们也不作网卡),因此有些书并不把这个层次放在tcp/ip协议族里面,由于它几乎和tcp/ip协议的编写者没有任何的关系。发送协议的主机从上自下将数据按照协议封装,而接收数据的主机则按照协议从获得的数据包解开,最后拿到须要的数据。这种结构很是有栈的味道,因此某些文章也把tcp/ip协议族称为tcp/ip协议栈。编程
在学习协议以前,咱们应该具有一些基本知识。windows
网络上每个节点都必须有一个独立的Internet地址(也叫作IP地址)。如今,一般使用的IP地址是一个32bit的数字,也就是咱们常说的IPv4标准,这32bit的数字分红四组,也就是常见的255.255.255.255的样式。IPv4标准上,地址被分为五类,咱们经常使用的是B类地址。具体的分类请参考其余文档。须要注意的是IP地址是网络号+主机号的组合,这很是重要。缓存
域名系统是一个分布的数据库,它提供将主机名(就是网址啦)转换成IP地址的服务。安全
RFC是什么?RFC就是tcp/ip协议的标准文档,在这里咱们能够看到RFC那长长的定义列表,如今它一共有4000多个协议的定义,固然,咱们所要学习的,也就是那么十几个协议而已。服务器
注意,这个号码是用在TCP,UDP上的一个逻辑号码,并非一个硬件端口,咱们平时说把某某端口封掉了,也只是在IP层次把带有这个号码的IP包给过滤掉了而已。
如今经常使用的编程接口有socket和TLI。而前面的有时候也叫作“Berkeley socket”,可见Berkeley对于网络的发展有多大的贡献。
数据链路层有三个目的:
ip你们都据说过。至于ARP和RARP,ARP叫作地址解析协议,是用IP地址换MAC地址的一种协议,而RARP则叫作逆地址解析协议,在tcp/ip协议的后面章节会介绍它们(在局域网里面用ARP协议能够很容易的搞瘫痪网络哦)
数据链路层的协议仍是不少的,有咱们最经常使用的以太网(就是平时咱们用的网卡)协议,也有不太常见的令牌环,还有FDDI,固然,还有国内如今至关普及的PPP协议(就是adsl宽带),以及一个loopback协议。
联系linux里面的ifconfig -a命令,这个命令一般会获得以下的结果
eth0 Link encap:Ethernet HWaddr 00:01:4A:03:5B:ED
inet addr:192.168.11.2 Bcast:192.168.11.255 Mask:255.255.255.0
inet6 addr: fe80::201:4aff:fe03:5bed/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2819 errors:0 dropped:0 overruns:0 frame:0
TX packets:76 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:241609 (235.9 KiB) TX bytes:9596 (9.3 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:2713 errors:0 dropped:0 overruns:0 frame:0
TX packets:2713 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3516032 (3.3 MiB) TX bytes:3516032 (3.3 MiB)
其中,eth0就是以太网接口,而lo则是loopback接口。这也说明这个主机在网络链路层上至少支持loopback协议和以太网协议。
以太网(Ether-net)的定是指数字设备公司( Digital Equipment Corp.)、英特尔公司(Intel Corp.)和Xerox公司在1982年联合公布的一个标准,这个标准里面使用了一种称做CSMA/CD的接入方法。而IEEE802提供的标准集802.3(还有一部分定义到了802.2中)也提供了一个CSMA/CD的标准。这两个标准稍有不一样,TCP/IP协议对这种状况的处理方式以下:
可见,RFC1042在TCP/IP里面处于一个配角的地位。这两种不一样的数据报格式请参考教材。
ppp(点对点协议)是从SLIP的替代品。他们都提供了一种低速接入的解决方案。而每一种数据链路层协议,都有一个MTU(最大传输单元)定义,在这个定义下面,若是IP数据报过大,则要进行分片(fragmentation),使得每片都小于MTU,注意PPP的MTU并非一个物理定义,而是指一个逻辑定义(我的认为就是用程序控制)。能够用netstat来打印出MTU的结果,好比键入netstat -in
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 1774 0 0 0 587 0 0 0 BMRU
lo 16436 0 2667 0 0 0 2667 0 0 0 LRU
就能够观察到eth0的MTU是1500。而lo(环回接口)的MTU则是16436。
最后说说那个环回接口(loopback)。平时咱们用127.0.0.1来尝试本身的机器服务器好使很差使。走的就是这个loopback接口。对于环回接口,有以下三点值得注意:
这一章仍是很简单的,通常做为了解知识也就足够了,不必抠的那么详细。
TCP/IP详解学习笔记(3)-IP协议,ARP协议,RARP协议
把这三个协议放到一块儿学习是由于这三个协议处于同一层,ARP协议用来找到目标主机的Ethernet网卡Mac地址,IP则承载要发送的消息。数据链路层能够从ARP获得数据的传送信息,而从IP获得要传输的数据信息。
IP协议是TCP/IP协议的核心,全部的TCP,UDP,IMCP,IGCP的数据都以IP数据格式传输。要注意的是,IP不是可靠的协议,这是说,IP协议没有提供一种数据未传达之后的处理机制--这被认为是上层协议--TCP或UDP要作的事情。因此这也就出现了TCP是一个可靠的协议,而UDP就没有那么可靠的区别。这是后话,暂且不提
1.1.IP协议头
如图所示
挨个解释它是教科书的活计,我感兴趣的只是那八位的TTL字段,还记得这个字段是作什么的么?这个字段规定该数据包在穿过多少个路由以后才会被抛弃(这里就体现出来IP协议包的不可靠性,它不保证数据被送达),某个ip数据包每穿过一个路由器,该数据包的TTL数值就会减小1,当该数据包的TTL成为零,它就会被自动抛弃。这个字段的最大值也就是255,也就是说一个协议包也就在路由器里面穿行255次就会被抛弃了,根据系统的不一样,这个数字也不同,通常是32或者是64,Tracerouter这个工具就是用这个原理工做的,tranceroute的-m选项要求最大值是255,也就是由于这个TTL在IP协议里面只有8bit。
如今的ip版本号是4,因此也称做IPv4。如今还有IPv6,并且运用也愈来愈普遍了。
1.2.IP路由选择
当一个IP数据包准备好了的时候,IP数据包(或者说是路由器)是如何将数据包送到目的地的呢?它是怎么选择一个合适的路径来"送货"的呢?
最特殊的状况是目的主机和主机直连,那么主机根本不用寻找路由,直接把数据传递过去就能够了。至因而怎么直接传递的,这就要靠ARP协议了,后面会讲到。
稍微通常一点的状况是,主机经过若干个路由器(router)和目的主机链接。那么路由器就要经过ip包的信息来为ip包寻找到一个合适的目标来进行传递,好比合适的主机,或者合适的路由。路由器或者主机将会用以下的方式来处理某一个IP数据包
这再一次证实了,ip包是不可靠的。由于它不保证送达。
1.3.子网寻址
IP地址的定义是网络号+主机号。可是如今全部的主机都要求子网编址,也就是说,把主机号在细分红子网号+主机号。最终一个IP地址就成为 网络号码+子网号+主机号。例如一个B类地址:210.30.109.134。通常状况下,这个IP地址的红色部分就是网络号,而蓝色部分就是子网号,绿色部分就是主机号。至于有多少位表明子网号这个问题上,这没有一个硬性的规定,取而代之的则是子网掩码,校园网相信大多数人都用过,在校园网的设定里面有一个255.255.255.0的东西,这就是子网掩码。子网掩码是由32bit的二进制数字序列,形式为是一连串的1和一连串的0,例如:255.255.255.0(二进制就是11111111.11111111.11111111.00000000)对于刚才的那个B类地址,由于210.30是网络号,那么后面的109.134就是子网号和主机号的组合,又由于子网掩码只有后八bit为0,因此主机号就是IP地址的后八个bit,就是134,而剩下的就是子网号码--109。
2. ARP协议
还记得数据链路层的以太网的协议中,每个数据包都有一个MAC地址头么?咱们知道每一块以太网卡都有一个MAC地址,这个地址是惟一的,那么IP包是如何知道这个MAC地址的?这就是ARP协议的工做。
ARP(地址解析)协议是一种解析协议,原本主机是彻底不知道这个IP对应的是哪一个主机的哪一个接口,当主机要发送一个IP包的时候,会首先查一下本身的ARP高速缓存(就是一个IP-MAC地址对应表缓存),若是查询的IP-MAC值对不存在,那么主机就向网络发送一个ARP协议广播包,这个广播包里面就有待查询的IP地址,而直接收到这份广播的包的全部主机都会查询本身的IP地址,若是收到广播包的某一个主机发现本身符合条件,那么就准备好一个包含本身的MAC地址的ARP包传送给发送ARP广播的主机,而广播主机拿到ARP包后会更新本身的ARP缓存(就是存放IP-MAC对应表的地方)。发送广播的主机就会用新的ARP缓存数据准备好数据链路层的的数据包发送工做。
一个典型的arp缓存信息以下,在任意一个系统里面用“arp -a”命令:
Interface: 192.168.11.3 --- 0x2
Internet Address Physical Address Type
192.168.11.1 00-0d-0b-43-a0-2f dynamic
192.168.11.2 00-01-4a-03-5b-ea dynamic
都会获得这样的结果。
这样的高速缓存是有时限的,通常是20分钟(伯克利系统的衍生系统)。
TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute
1.IMCP协议介绍
前面讲到了,IP协议并非一个可靠的协议,它不保证数据被送达,那么,天然的,保证数据送达的工做应该由其余的模块来完成。其中一个重要的模块就是ICMP(网络控制报文)协议。
当传送IP数据包发生错误--好比主机不可达,路由不可达等等,ICMP协议将会把错误信息封包,而后传送回给主机。给主机一个处理错误的机会,这 也就是为何说创建在IP层以上的协议是可能作到安全的缘由。ICMP数据包由8bit的错误类型和8bit的代码和16bit的校验和组成。而前 16bit就组成了ICMP所要传递的信息。书上的图6-3清楚的给出了错误类型和代码的组合表明的意思。
尽管在大多数状况下,错误的包传送应该给出ICMP报文,可是在特殊状况下,是不产生ICMP错误报文的。以下
虽然里面的一些规定如今还不是很明白,可是全部的这一切规定,都是为了防止产生ICMP报文的无限传播而定义的。
ICMP协议大体分为两类,一种是查询报文,一种是差错报文。其中查询报文有如下几种用途:
而差错报文则产生在数据传送发生错误的时候。就不赘述了。
2.ICMP的应用--ping
ping能够说是ICMP的最著名的应用,当咱们某一个网站上不去的时候。一般会ping一下这个网站。ping会回显出一些有用的信息。通常的信息以下:
Reply from 10.4.24.1: bytes=32 time<1ms TTL=255
Reply from 10.4.24.1: bytes=32 time<1ms TTL=255
Reply from 10.4.24.1: bytes=32 time<1ms TTL=255
Reply from 10.4.24.1: bytes=32 time<1ms TTL=255
Ping statistics for 10.4.24.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
ping这个单词源自声纳定位,而这个程序的做用也确实如此,它利用ICMP协议包来侦测另外一个主机是否可达。原理是用类型码为0的ICMP发请 求,受到请求的主机则用类型码为8的ICMP回应。ping程序来计算间隔时间,并计算有多少个包被送达。用户就能够判断网络大体的状况。咱们能够看到, ping给出来了传送的时间和TTL的数据。我给的例子不太好,由于走的路由少,有兴趣地能够ping一下国外的网站好比sf.net,就能够观察到一些 丢包的现象,而程序运行的时间也会更加的长。
ping还给咱们一个看主机到目的主机的路由的机会。这是由于,ICMP的ping请求数据报在每通过一个路由器的时候,路由器都会把本身的ip放到该数 据报中。而目的主机则会把这个ip列表复制到回应icmp数据包中发回给主机。可是,不管如何,ip头所能纪录的路由列表是很是的有限。若是要观察路由, 咱们仍是须要使用更好的工具,就是要讲到的Traceroute(windows下面的名字叫作tracert)。
3.ICMP的应用--Traceroute
Traceroute是用来侦测主机到目的主机之间所经路由状况的重要工具,也是最便利的工具。前面说到,尽管ping工具也能够进行侦测,可是,由于ip头的限制,ping不能彻底的记录下所通过的路由器。因此Traceroute正好就填补了这个缺憾。
Traceroute的原理是很是很是的有意思,它受到目的主机的IP后,首先给目的主机发送一个TTL=1(还记得TTL是什么吗?)的UDP(后面就 知道UDP是什么了)数据包,而通过的第一个路由器收到这个数据包之后,就自动把TTL减1,而TTL变为0之后,路由器就把这个包给抛弃了,并同时产生 一个主机不可达的ICMP数据报给主机。主机收到这个数据报之后再发一个TTL=2的UDP数据报给目的主机,而后刺激第二个路由器给主机发ICMP数据 报。如此往复直到到达目的主机。这样,traceroute就拿到了全部的路由器ip。从而避开了ip头只能记录有限路由IP的问题。
有人要问,我怎么知道UDP到没到达目的主机呢?这就涉及一个技巧的问题,TCP和UDP协议有一个端口号定义,而普通的网络程序只监控少数的几个号码较 小的端口,好比说80,好比说23,等等。而traceroute发送的是端口号>30000(真变态)的UDP报,因此到达目的主机的时候,目的 主机只能发送一个端口不可达的ICMP数据报给主机。主机接到这个报告之后就知道,主机到了,因此,说Traceroute是一个骗子一点也不为过:)
Traceroute程序里面提供了一些颇有用的选项,甚至包含了IP选路的选项,请察看man文档来了解这些,这里就不赘述了。
TCP/IP详解学习笔记(5)-IP选路,动态选路,和一些细节
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。
U没啥可说的,G说明这是一个网关,若是你要发数据给Destination,IP头应该写Destination的IP地址,而数据链路层的MAC地址就应该是GateWay的Mac地址了;反之,若是没有G标志,那么数据链路层和IP层的地址应该是对应的。H说明了Destination的性质,若是是H的,则说明该地址是一个完整的地址,既有网络号又有主机号,那么再匹配的时候就既要匹配网络号,又要匹配主机号;反之,Destination就表明一个网络,在匹配的时候只要匹配一下网络号就能够了。
这样,IP选路的方式就能够更加具体化了。以下
顺便提一下那个GenMask(还记得子网掩码么),它指定了目的地址的子网号,例如第一条的子网就是11。
1.2.其余有关路由表的知识
通常,咱们在配置好一个网络接口的时候,一个路由就被直接建立好了。固然咱们也能够手动添加路由。用route add命令就能够了。
而当一个IP包在某一个路由器的时候发现没有路由可走,那么该路由器就会给源主机发送“主机不可达”或者“网络不可达”的ICMP包来报错。
注意,通常的操做系统默认是没有路由功能的,这须要本身配置。这些历史缘由就不细说了,
1.3.ICMP的IP重定向报文和路由发现报文
当IP包在某一个地方转向的时候,都回给发送IP报的源主机一个ICMP重定向报文,而源主机就能够利用这个信息来更新本身的路由表,这样,随着网络通讯的逐渐增多,路由表也就愈来愈完备,数据转发的速度也会愈来愈快。咱们须要注意的是:
在主机引导的时候,通常会发送在网内广播一个路由请求的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则支持RIPv1、v2,BGPv1 等等。
2.1.RIP:选路信息协议
它的定义能够在RFC1058内找到,这种协议使用UDP做为载体(也就是UDP的上层协议)。咱们最关心的就是RIP其中的一个段,叫作度量的段,这是一个以hop做为计数器(就是以走过多少路由为计数器)的段(IP协议里面也有一个TTL不是么)。这个度量段将最终影响到路由表的创建。参考图:
通常说来routed要承担以下的工做:
这个协议看起来会工做的很好,可是,这里面其实有不少隐藏的忧患,好比说RIP没有子网的概念,好比说环路的危险。并且hop数的上限也限制了网络的大小。
所以,出现了不少RIPv1的替代品,好比说RIPv2,好比说OSPF。他们都是经过某种策略来影响路由表,因此就不说了。
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报文。
UDP协议的某些特性将会影响咱们的服务器程序设计,大体总结以下:
5.
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发信。
再来一个多播的例子,可是要实现这个多播并不容易,由于我不知道网络内有多少个多播组,就只好利用几个特殊的多播地址来验证了。
对于多播地址,有几个特殊的多播地址被占用,他们是
因此只要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差错(不必)。
前面已经提到了访问一台机器要靠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页。对各个字段简单解释以下
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查询的有两种状况:
终于看到了TCP协议,这是TCP/IP详解里面最重要也是最精彩的部分,要花大力气来读。前面的TFTP和BOOTP都是一些简单的协议,就不写笔记了,写起来也没啥东西。
TCP和UDP处在同一层---运输层,可是TCP和UDP最不一样的地方是,TCP提供了一种可靠的数据传输服务,TCP是面向链接的,也就是说,利用TCP通讯的两台主机首先要经历一个“拨打电话”的过程,等到通讯准备结束才开始传输数据,最后结束通话。因此TCP要比UDP可靠的多,UDP是把数据直接发出去,而无论对方是否是在收信,就算是UDP没法送达,也不会产生ICMP差错报文,这一经时重申了不少遍了。
把TCP保证可靠性的简单工做原理摘抄以下
从这段话中能够看到,TCP中保持可靠性的方式就是超时重发,这是有道理的,虽然TCP也能够用各类各样的ICMP报文来处理这些,可是这也不是可靠的,最可靠的方式就是只要不获得确认,就从新发送数据报,直到获得对方的确认为止。
TCP的首部和UDP首部同样,都有发送端口号和接收端口号。可是显然,TCP的首部信息要比UDP的多,能够看到,TCP协议提供了发送和确认所须要的全部必要的信息。这在P171-173有详细地介绍。能够想象一个TCP数据的发送应该是以下的一个过程。
能够想见,为了创建一个TCP链接,系统可能会创建一个新的进程(最差也是一个线程),来进行数据的传送
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更佳的小的话,这个值还会变得更小。
3. TCP的状态迁移图
下面的文章按照client/server两条路线讲述TCP状态迁移路线图。
书P182页给出了TCP的状态图,这是一个看起来比较复杂的状态迁移图,由于它包含了两个部分---服务器的状态迁移和客户端的状态迁移,若是从某一个角度出发来看这个图,就会清晰许多,这里面的服务器和客户端都不是绝对的,发送数据的就是客户端,接受数据的就是服务器。
1. 链接创建
1) Client
当Client端调用socket函数调用时,至关于Client端产生了一个处于Closed状态的套接字。
Client端又调用connect函数调用,系统为Client随机分配一个端口,连同传入connect中的参数(Server的IP和端口),这就造成了一个链接四元组,connect调用让Client端的socket处于SYN_SENT状态
当Server返回确认,并发送SYN,Client返回确认及SYN后,套接字处于ESTABLISHED阶段,此时双方的链接已经能够进行读写操做
2)Server
当Server端调用socket函数调用时,至关于Server端产生了一个处于Closed状态的监听套接字.
Server端调用bind操做,将监听套接字与指定的地址和端口关联,而后又调用listen函数,系统会为其分配未完成队列和完成队列,此时的监听套接字能够接受Client的链接,监听套接字状态处于LISTEN状态。
当Server端调用accept操做时,会从完成队列中取出一个已经完成的client链接,同时在server这段会产生一个会话套接字,用于和client端套接字的通讯,这个会话套接字的状态是ESTABLISH。
2. 链接关闭
与链接创建分为server/client不一样,链接关闭并无绝对的server/client之分,链接关闭分为主动关闭和被动关闭。Server和client均可以担任这两个角色中的任意一个。如client能够关闭它与server的链接,一样的server同样也能够关闭一些长时间无读写事件发生的链接。既然这么说了,下面就会分红两个部分:client主动关闭,server主动关闭。
Client主动关闭,Server被动关闭:
Client主动关闭,Server被动关闭的状况仍是蛮多的,好比说短链接中,当一次会话结束时,client就能够关闭它与server之间的链接。咱们这边直接说close而非shutdown。
当client想要关闭它与server之间的链接,首先client这边会首先调用close函数,client端会发送一个FIN到server端,client端处于FIN_WAIT1状态。当server端返回给client ACK后,client处于FIN_WAIT2状态,server处于CLOSE_WAIT状态。
当server端检测到client端的关闭操做(read返回为0),server端也须要调用close操做,server端会向client端发送一个FIN。此时server的状态为LAST_ACK,当client收到来自server的FIN后,client端的套接字处于TIME_WAIT状态,它会向server端再发送一个ack确认,此时server端收到ack确认后,此套接字处于CLOSED状态。
Server端主动关闭的流程与Client端关闭相似,就再也不多讲,下面还须要关注的是TIME_WAIT这个状态,分别按照client/server两个部分讲述。
首先说一下TCP/IP详解中描述的关于TIME_WAIT的描述及其存在的必要性:
主动关闭的socket当收到对端的FIN操做后,该socket就会处于TIME_WAIT状态,处于TIME_WAIT状态的socket会存活2MSL(Max Segment Lifetime),之因此存活这么长时间是有理由的:
一方面是可靠的实现TCP全双工链接的终止,也就是当最后的ACK丢失后,被动关闭端会重发FIN,所以主动关闭端须要维持状态信息,以容许它从新发送最终的ACK。
另外一方面TCP在2MSL等待期间,定义这个链接(4元组)不能再使用,任何迟到的报文都会丢弃。设想若是没有2MSL的限制,刚好新到的链接正好知足原先的4元组,这时候链接就可能接收到网络上的延迟报文就可能干扰最新创建的链接。
另外一方面是为了重复的分节在网络中消逝。对于
另外一方面是网络上仍然可能有残余的数据包
当Client主动关闭时,正常状况下client的socket会经历TIME_WAIT的状态
链接在关闭的时候,双方都会有状态的迁移,这就要求咱们的程序中必定要有比较彻底的
3. Server端的监听套接字与会话套接字的不一样:
当server端的socket调用bind和listen以后,监听套接字的状态就会变为LISTEN状态,监听套接字的工做决定了它只是监听链接。
当server端调用accept,至关于从套接字的完成队列中取出一个client的链接,此时能够肯定四元组,即:client的IP和port;server的IP和port,双方各有一个套接字进行交互,这里须要说一下server端的socket,我称server端accept后产生的套接字为会话套接字,这个套接字一出生的状态就是ESTABLISH
由server端得四元组咱们能够看出,一个server从理论上能够接收的链接数量取决于文件描述符的个数。
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.其余状态迁移
书中的图还有一些其余的状态迁移,这些状态迁移针对服务器和客户端两方面的总结以下
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状态,而直到应用层来决定关闭这个状态。
RST是另外一种关闭链接的方式,应用程序应该能够判断RST包的真实性,便是否为异常停止。而同时打开和同时关闭则是两种特殊的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很好的解释了这一点。
关于滑动窗口协议,书上还介绍了三个术语,分别是:
TCP就是用这个窗口,慢慢的从数据的左边移动到右边,把处于窗口范围内的数据发送出去(但不用发送全部,只是处于窗口内的数据能够发送。)。这就是窗口的意义。图20-6解释了这一点。窗口的大小是能够经过socket来制定的,4096并非最理想的窗口大小,而16384则能够使吞吐量大大的增长。
2.3.数据拥塞
上面的策略用于局域网内传输还能够,可是用在广域网中就可能会出现问题,最大的问题就是当传输时出现了瓶颈(好比说必定要通过一个slip低速链路)所产生的大量数据堵塞问题(拥塞),为了解决这个问题,TCP发送方须要确认链接双方的线路的数据最大吞吐量是多少。这,就是所谓的拥塞窗口。
拥塞窗口的原理很简单,TCP发送方首先发送一个数据报,而后等待对方的回应,获得回应后就把这个窗口的大小加倍,而后连续发送两个数据报,等到对方回应之后,再把这个窗口加倍(先是2的指数倍,到必定程度后就变成现行增加,这就是所谓的慢启动),发送更多的数据报,直到出现超时错误,这样,发送端就了解到了通讯双方的线路承载能力,也就肯定了拥塞窗口的大小,发送方就用这个拥塞窗口的大小发送数据。要观察这个现象是很是容易的,咱们通常在下载数据的时候,速度都是慢慢“冲起来的”
以上就是TCP数据传输的大体流程,虽然并不细致,可是足以描述TCP的工做原理,重点是TCP的流量控制原理,滑动窗口,拥塞窗口,ACK累计确认等知识点。
超时重传是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.计时器的使用
两句话:
2.重传
有了超时就要有重传,可是就算是重传也是有策略的,而不是将数据简单的发送。
2.1.重传时发送数据的大小
前面曾经提到过,数据在传输的时候不能只使用一个窗口协议,咱们还须要有一个拥塞窗口来控制数据的流量,使得数据不会一会儿都跑到网路中引发“拥塞”。也曾经提到过,拥塞窗口最初使用指数增加的速度来增长自身的窗口,直到发生超时重传,再进行一次微调。可是没有提到,如何进行微调,拥塞避免算法和慢启动门限就是为此而生。
所谓的慢启动门限就是说,当拥塞窗口超过这个门限的时候,就使用拥塞避免算法,而在门限之内就采用慢启动算法。因此这个标准才叫作门限,一般,拥塞窗口记作cwnd,慢启动门限记作ssthresh。下面咱们来看看拥塞避免和慢启动是怎么一块儿工做的
算法概要(直接从书中拷贝)
补充上面的拥塞避免公式在P238页。这整个的流程让我联想到开车换档的过程。
2.2.快速重传和快速恢复算法
这是数据丢包的状况下给出的一种修补机制。通常来讲,重传发生在超时以后,可是若是发送端接受到3个以上的重复ACK的状况下,就应该意识到,数据丢了,须要从新传递。这个机制是不须要等到重传定时器溢出的,因此叫作快速重传,而从新传递之后,由于走的不是慢启动而是拥塞避免算法,因此这又叫作快速恢复算法。流程以下:
答案是:不会,TCP会坚持用本身的定时器,可是TCP会保留下ICMP的错误而且通知用户。
TCP为了提升本身的效率,容许再从新传输的时候,只要传输包含重传数据报文的报文就能够,而不用只重传须要传输的报文。
TCP/IP详解学习笔记(13)-TCP坚持定时器,TCP保活定时器
TCP一共有四个主要的定时器,前面已经讲到了一个--超时定时器--是TCP里面最复杂的一个,另外的三个是:
其中坚持定时器用于防止通告窗口为0之后双方互相等待死锁的状况;而保活定时器则用于处理半开放链接
1.坚持定时器
坚持定时器的原理是简单的,当TCP服务器收到了客户端的0滑动窗口报文的时候,就启动一个定时器来计时,并在定时器溢出的时候向向客户端查询窗口是否已经增大,若是获得非零的窗口就从新开始发送数据,若是获得0窗口就再开一个新的定时器准备下一次查询。经过观察能够得知,TCP的坚持定时器使用1,2,4,8,16……64秒这样的普通指数退避序列来做为每一次的溢出时间。
糊涂窗口综合症
TCP的窗口协议,会引发一种一般叫作糊涂窗口综合症的问题,具体表现为,当客户端通告一个小的非零窗口时,服务器马上发送小数据给客户端并充满其缓冲区,一来二去就会让网络中充满小TCP数据报,从而影响网络利用率。对于发送方和接收端的这种糊涂行为。TCP给出了一些建议(或者是规定)。
ok,如今咱们回忆一下,能够发现TCP的不少规定都是为了在一次传送中发送尽可能多的数据,例如捎带ACK数据报文的策略,Nagle算法,重传时发送包含原数据报文的策略,等等。
2.保活定时器
保活定时器更加的简单,还记得FTP或者Http服务器都有Sesstion Time机制么?由于TCP是面向链接的,因此就会出现只链接不传送数据的“半开放链接”,服务器固然要检测到这种链接而且在某些状况下释放这种链接,这就是保活定时器的做用。其时限根据服务器的实现不一样而不通。另外要提到的是,当其中一端若是崩溃并从新启动的状况下,若是收到该端“前生”的保活探察,则要发送一个RST数据报文帮助另外一端结束链接。
转载于 http://blog.csdn.net/goodboy1881