链路层
以太网帧格式
- 其中的目的地址和源地址是指网卡的硬件地址(MAC地址),长度48位,是在网卡出场时固化的。
- 网卡芯片收到的数据就是如上所示的一长串数据;其中包括以太网帧头,IP报报头,传输层协议段段头和应用层所需数据。
- 以太网帧的“数据长度”规定最小46字节,最大1500字节,ARP和RARP数据包的长度不足46字节要在后面填充。最大1500字节也被称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU。
- 以太网帧最后有4字节的帧检验序列码,发送方计算帧的循环冗余校验(CRC)值,把它写进帧里,接收方重新计算CRC,与帧检验序列码比较,如果两个值不同,说明数据错误,需要重新传输。
ARP地址解析协议(通常被划分在网络层)
通过IP地址来查找MAC地址
工作流程:
- 本地主机在局域网中广播ARP请求,ARP请求数据帧中包含目的主机的IP地址。意思是:如果你是IP地址的拥有者,请应答你的MAC地址。
- 目的主机的ARP层解析这份广播报文,识别出是询问其MAC地址。于是发送ARP应答帧,里面包含自己的IP地址和MAC地址。
- 本地主机收到ARP应答帧后,知道了目的地址的硬件地址,之后的数据报就可以传送了。
RARP逆地址解析协议:知道物理地址来查找IP地址。
应用:局域网中有一台主机只知道物理地址而不知道IP地址,那么可以通过RARP协议发出征求自身IP地址的广播请求,然后由RARP服务器负责回答。无盘工作站引导时获取IP地址。
RARP帧与ARP帧通过2字节的帧类型字段来区别。
ARP缓存
ARP缓存本质上是一个IP地址→MAC地址的对应表,表中每一个条目记录了网络上其他主机的IP地址和对应的MAC地址。当ARP被询问一个已知IP地址节点的MAC地址时,先在ARP缓存中查看,若存在,则直接返回与之对应的MAC地址,若不存在,才发送ARP请求广播。表中每一项都有TTL(生存时间)值,时间到了该值后,该项被删除;在表中查找到某一项时,刷新该项的TTL。ARP缓存时把双刃剑,虽然增加了效率,但会导致容易被篡改攻击。
网络层
链路层的任务是两节点间可靠的数据传输,而网络层的任务是两端点间的最佳路由传输数据(主机间的逻辑通信)。
根据端到端的设计原则,IP只为主机提供一种无连接、不可靠、尽力而为的数据报传输服务。
IP报文格式(IPv4)
首部的固定部分为20字节,加上可选字段,首部最长可以有60字节。
下面分别介绍固定部分的字段含义:
- 4位版本协议(version):通信双方的IP协议必须要达到一致,IPv4的版本就是4。
- 4位首部长度(header length):定义了IP协议首部(报头)的长度,以4个字节为单位,首部长度范围[5,15],即[20字节,60字节]。
- 8位服务类型(Type Of Service,TOS):3 位优先权字段(已经弃用), 4位TOS字段, 和一位保留字段(此位必须置0), 4位TOS分别表示 : 最小延迟, 最大吞吐量, 最高可靠性, 最小成本。这四者相互冲突, 只能有一个置1。对于ssh/telnet这样的应用程序, 最小延时比较重要, 对于ftp(文件传输协议)类型的程序, 最大吞吐量比较重要。
- 16位(分片)标识:在进行数据分片重组的时候表示数据分片属于那个完整的UDP报文, 具体来说, IP在存储器中维持一个计数器, 每产生一个数据报, 计数器就加1, 并将此值赋给标识字段。但这个标识并不是平常的序号,因为IP是无连接,不可靠服务, 数据报不存在按序接收的问题。当数据报由于长度超过链路层的MTU而必须分片时, 这个标识字段的值就被复制到所有的数据报片的标识字段中, 等到对端重组的时候, 相同标识符的值的数据报就会被重新组装成一个数据报。
- 3位(分片)标志:高位未用,中间位DF置1,表示不能进行分片,置0才可以进行分片操作。最低为MF,置1表示后面还有数据分片,置0表示这已经是最后一个数据分片了。
- 13位片偏移:标识一个分片在原始UDP报文中的位置,以8字节为单位,例如将一个1001字节的UDP报文按256字节分片后,第一片的数据报的片偏移就是0,第二片数据报的片偏移就是256/8=32,第三片就是512/8=64,第四片就是768/8=96,第四片并没有256个字节,如果分片前的数据不能被8整除,那分片后的最后一个数据大小就是分片前数据报大小除以8的余数。所以不管分片前的大小能不能被8整除,片偏移永远是8的整数倍。
- 8位TTL:报文在网络中的生存周期,即跳数,指的是能够经过多少路由器,每经过一个路由器就成为1跳,该值就减1,为0时就被丢弃,最大值为2^8-1=255。
- 8位协议:标时传输层使用的时什么协议,用于数据分用。
- 16位校验和:二进制反码求和,用于校验数据的一致性。
- 32位源地址/32位目的地址:用于标识源端/对端主机,路由器就是根据对端主机IP地址进行路径选择的。
- 可选字段(不定长,最多40字节):基本很少用到。
IP分片
由于路由器转发数据报时不同的链路能够容纳的数据报的大小不同,所以当数据报从大的链路通过路由器转发到小的链路上时,需要进行IP分片,到最后的链路上再组合好。
数据报大于MTU,需要分段,4000B/1480B向上取整等于3,因此需要分3片。
除了最后一片,前面的分片都为MTU允许的最大分片。
第一片1480B加上首部20B等于1500B,片偏移0。
第二片1480B加上首部20B等于1500B,片偏移1480/8=185。
第三片还剩余1040B,加上首部20B等于1060B,片偏移(1480+1480)/8=370。设置MF=0,没有更多分片。
IP选路
IP选路,即IP寻路,就是根据路由表中的记录,来决定当前数据报是直接交付(目的地址属于当前局域网)还是发往下一跳路由(隶属于不同的局域网)。
选路原则:
- 搜索匹配的主机地址;
- 搜索匹配的网络地址;
- 搜索默认表项(一般是0.0.0.0)
匹配主机地址步骤始终发生在匹配网络地址步骤之前。搜索网络地址时,会将IP地址与子网掩码相与运算,看结果与网络地址是否相同。
ICMP协议
一个新搭建好的网络,往往需要先进行一个简单的测试,来验证网络是否通畅,但是IP协议并不提供可靠传输。如果丢包了,IP协议并不能通知传输层是否丢包以及丢包的原因。
所以我们就需要一种协议来完成这样的功能——ICMP协议。
ICMP协议的功能主要有:
- 确认IP包是否成功到达目标地址
- 通知在发送过程中IP包被丢弃的原因
注意:
- ICMP是基于IP协议工作的,但是它并不是传输层的功能,因此仍然把它归结为网络层协议。
- ICMP只能搭配IPv4使用,如果是IPv6的情况,需要使用ICMPv6
ICMP的报文格式
ICMP报文包含在IP数据报中,IP报头在ICMP报文的最前面。一个ICMP报文包括IP报头(至少20字节)、ICMP报头(至少8字节)和ICMP报文(属于ICMP报文的数据部分)。当IP报头中的协议字段为1时,就说明这是一个ICMP报文。
字段说明:
类型 | 说明 |
---|---|
类型 | 占1字节,标识ICMP报文的类型,从类型值来看ICMP报文可以分为两大类。第一类是取值为1~127的差错报文,第二类是取值128以上的信息报文 |
代码 | 占1字节,标识ICMP报文的代码。它与类型字段一起共同标识了ICMP报文的详细类型 |
校验和 | 这时对包含ICMP报文数据部分在内的整个ICMP数据报的校验和,以检验报文在传输过程中是否出现了差错(其计算方法与在我们介绍IP报头中的校验和计算方法是一样的) |
ICMP大概分为两类报文:
一类是通知出错原因,一类是用于诊断查询
类型及含义如下:
类型(十进制) | 内容 |
---|---|
0 | 回送应答 |
3 | 目标不可达 |
4 | 原点抑制 |
5 | 重定向或改变路由 |
8 | 回送请求 |
9 | 路由器公告 |
10 | 路由器请求 |
11 | 超时 |
17 | 地址子网请求 |
18 | 地址子网应答 |
常见的ICMP报文
- 响应请求
我们用的ping操作中就包括了响应请求(类型字段值为8)和应答(类型字段值为0)ICMP报文。
一台主机向一个节点发送一个类型字段值为8的ICMP报文,如果途中没有异常(没有被路由丢弃,目标不回应或者传输失败),则目标返回类型字段值为0的ICMP报文,说明这台主机存在。 - 目标不可达,源抑制和超时报文
这三种报文的格式是一样的。
目标不可达报文(类型值为3)在路由器或主机不能传递数据时使用。
源抑制报文(4)则充当一个控制流量的角色,通知主机减少数据报流量。
超时报文的(11)的代码域有两种取值:0表示传输超时,1表示分段重组超时。 - 时间戳请求
时间戳请求报文(13)和时间戳应答报文(14)用于测试两台主机之间数据报来回一次的传输时间。
传输层
端口号:用一个16位端口号进行标识,允许2^16=65536个端口号。端口号具有本地意义,即端口号只是为了标识本计算机应用层中的各进程。
- 熟知端口/保留端口(服务端端口):数值为0-1023,当TCP/IP一些重要的应用出现时,必须为它指派一个熟知端口,以便其他应用进程与其交互。
- 登记端口:数值为1024-49151。为没有熟知端口号的应用程序使用的,使用这类端口号必须在IANA登记,以防止重复。
- 短暂端口(客户端端口):数值为49152-65536。由于这类端口号仅在客户进程运行时才动态选择,所以称为短暂端口或临时端口。通信结束后,该端口自动空闲下来,提供其他客户进程使用。
应用程序 | FTP | TELNET | SMTP | DNS | TFTP | HTTP | SNMP |
熟知端口号 | 21 | 23 | 25 | 53 | 69 | 80 | 161 |
套接字:在网络中采用发送方和接收方的套接字组合识别端点,套接字唯一标识了网络中一个主机和该主机中的一个进程。
套接字Socket=(主机IP地址,端口号)
TCP连接::={socket1,socket2}={(IP1:port1),(IP2:port2)}
UDP协议
UDP的主要特点
UDP只在IP数据报服务之上增加了复用分用和差错检测功能。
复用指发送方不同的应用进程都可以使用同一个传输层协议传送数据。分用指接收方的传输层在剥去报文的首部后能够把这些数据正确地交付给目的应用进程。
- 传送数据前无需建立连接,数据到达后无需确认。减小开销和发送数据之前的时延。
- 不保证可靠交付。(交由应用层保证可靠交付)
- 面向报文,适合一次性传输少量数据的网络应用,报文头部短,传输开销小。
- 无拥塞控制,适合实时应用。
- 首部开销小,8B。TCP是20B。
- 应用层给UDP多长的报文,UDP只加上首部发送。即一次发送一个完整报文。
- 支持一对一,一对多,多对一,多对多的交互通信。
UDP报文段
UDP数据报的组成
TCP协议
TCP的主要特点
- 面向连接(虚连接),不提供广播或多播服务。
- 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。
- TCP提供可靠交付的服务,无差错、不丢失、不重复、按序到达。
- 提供全双工通信。两个端点都设置发送缓存(准备发送的数据和已发送但未到达的数据)和接受缓存(按序到达但未被应用程序读取的数据和没按序到达的数据)。
- 报文段头部长,传输开销大。
- 面向字节流。TCP把应用程序交下来的数据看成无结构的字节流。
TCP报文段
下面说明各字段的作用:
- 序号:TCP连接中传送的字节流中的每一个字节都是按顺序编号,该字段表示本报文段所发送的数据的第一个字节的序号。
- 确认号:期望收到对方下一个报文段的第一个数据字节的序号。若确认号为N,则证明序号N-1为止的所有数据已经确认收到。
- 数据偏移(首部长度):TCP报文段的数据起始距离TCP报文段的起始处有多远,以4B为单位。
- 紧急位URG:URG=1,表明此报文段有紧急数据,高优先级的数据,需要尽快传送,不需要在缓存里排队,搭配紧急指针字段使用。优先传送。
- 确认位ACK:ACK=1时确认号有效,建立连接后所有传送的报文段都必须将ACK置为1。
- 推送位PSH:PSH=1时,接收方尽快交付接收应用程序,不再等待缓存填满再向上交付。优先交付。
- 复位RST:RST=1时,表明TCP连接出现严重错误,必须释放连接,然后重新建立连接。
- 同步位SYN:SYN=1时,表明这是一个连接请求/连接接受报文。
- 终止位FIN:FIN=1时,释放连接。
- 窗口:指发送本报文段的一方的接收窗口,即允许对方发送的数据量。
- 检验和:检验首部加数据,检验时与UDP一样加上12B伪首部,协议字段为6。
- 紧急指针:URG=1时有意义,指本报文段中紧急数据的字节数。
- 选项:最大报文段长度MSS(每一个TCP报文段中的数据字段的最大长度,默认536B)、窗口扩大(3B)、时间戳(10B)、选择确认(SACK)。
在TCP报文段的首部中,只有端口号而没有IP地址。当TCP将其报文段交给IP层时,IP如何知道目的IP的地址的?
答:比如HTTP请求,DNS解析出IP地址后建立socket,然后进行connect系统调用的时候,IP地址实际上是作为参数传进去了,只不过TCP头部封装的时候没放进去,而是放在IP头里面了。
TCP连接管理
三次握手(申请连接)
TCP传输连接分为三个阶段:连接建立,数据传送,连接释放。
TCP连接的端点叫做套接字(socket)或插口。
TCP的连接和建立采用客户/服务器方式。主动发起连接建立的应用进程叫做客户(Client),被动等待连接建立的应用进程叫做服务器(Server)。
TCP传输连接的建立采用“三次握手”的方法。
采用三次握手的方法,目的是为了防止报文段在传输连接建立过程中出现差错。
步骤解析:
- 同步位SYN=1,随机产生一个序号seq=x。客户端发送连接请求报文,无应用层数据。
- 同步位SYN=1,确认位ACK=1,序号seq=y,确认号ack=x+1。服务器端为该TCP连接分配缓存和变量,并向客户端返回确认报文段,允许连接,无应用层数据。
- 同步位SYN=0,确认位ACK=1,序号seq=x+1,确认号ack=y+1。客户端为该TCP连接分配缓存和变量,并向服务端返回确认的确认,可以携带数据。
四次握手/挥手(释放连接)
- 数据传输结束后,通信双方都可以释放连接。现在客户端的应用进程先发送连接释放报文段,并停止发送数据,主动关闭TCP连接。客户端的应用进程将连接释放报文段首部的结束位FIN=1,序号seq=u,等待服务器确认。
- 服务器回送确认报文段,确认位ACK=1,确认号ack=u+1,序号seq=v。TCP服务器进程通知高层应用进程。从客户端到服务器这个方向的连接就释放了,TCP连接处于半关闭状态。服务器若发送数据,则客户端仍要接收。
- 若服务器已经没有要向客户端发送的数据,其应用进程发送连接释放报文段,结束位FIN=1,确认位ACK=1,序号seq=w,ack=u+1,服务器主动关闭TCP连接。
- 客户端收到连接释放报文段后,必须发出确认报文段,确认位ACK=1,确认号ack=w+1,序号seq=u+1。等待2MSL(时间等待计时器设置的最长报文段寿命,MSL=2min),期间若再次收到服务器发送的连接释放报文段(客户端确认报文段丢失),则重启时间等待计时器。2MSL时间后彻底关闭连接。(TIME_WAIT)
超时重传机制
TCP的发送方在重传时间内没有收到确认就重传已发送的报文段。
由于TCP的下层是一个互联网环境,IP数据报所选择的路由变化很大,所以运输层的往返时延的方差也很大。为了计算超时计时器的重传时间,TCP采用一种自适应的算法,动态改变重传时间RTTs(加权平均往返时间)。
超时重传等待时间结束后才重传,使用冗余确认方式,在超时事件发生之前,知道发送方是否丢失报文段。
TCP流量控制
流量控制:让发送方的发送速率不要太快,要让接收方来得及接收。
利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。
在通信过程中,接收方根据自己接收缓存的大小,动态地调整发送方的发送窗口大小,即接收窗口rwnd(接收方设置确认报文段的窗口字段来将rwnd通知给发送方)。发送方的发送窗口取接收窗口rwnd和拥塞窗口cwnd的最小值。
接收窗口为0时,当接收应用程序读取收数据后,接收窗口扩大,但发送方不发送数据,导致接收方无法发送确认告诉发送方接收窗口扩大,双方陷入死锁僵局。
TCP为每一个连接设有一个持续计时器。只要TCP连接的一方收到对方的0窗口通知,就启动持续计时器。
若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1B的数据),而对方就在确认探测报文段时给出现在的窗口值。
若窗口仍然是0,则接收到这个报文段的一方就重新设置持续计时器。若窗口不为0,则死锁僵局就被打破。
TCP拥塞控制
出现拥塞的条件:对资源需求的总和>可用资源
拥塞控制:防止过多的数据注入到网络中。
拥塞控制与流量控制的性质对比
- 拥塞控制所要做的只有一个前提,就是使得网络能够承受现有的网络负荷。
- 拥塞控制是一个全局性的过程,涉及网络中所有的主机、所有的路由器以及降低网络传输性能有关的所有因素。
- 流量控制往往指在给定的发送端和接收端之间的点对点通信量的控制。
- 流量控制所要做的就是抑制发送端发送数据的速率,以便接收端来得及接收。
- 拥塞控制很难设计,因为它是一个动态的问题。
- 当前网络正朝着高速化的方向发展,很容易出现缓存不够大而造成分组的丢失。分组的丢失是网络发生的征兆而不是原因。
- 在许多情况下,正是拥塞控制本身成为引起网络性能恶化甚至发生死锁的原因。
拥塞控制算法:
接收窗口:接收方根据接收缓存设置的值,并告知给发送方,反映接收方容量。
拥塞窗口:发送方根据自己估算的网络拥塞成都而设置的窗口值,反映网络当前容量。
慢开始和拥塞避免
慢开始原理:
- 在主机刚刚开始发送报文段时可先设置拥塞窗口cwnd=1。
- 在每收到一个对新的报文段的确认后,将拥塞窗口加1,即增加一个MSS的数值。相当于指数规律增长(翻倍)。
- 用该方法逐步增大发送端的拥塞窗口cwnd,可以使分组注入网络的速率更合理。
拥塞避免算法原理:
- 为防止拥塞窗口cwnd的增长引起网络阻塞,需要一个状态变量,即慢开始门限ssthresh。
- 当cwnd<ssthresh时,使用慢开始算法。
- 当cwnd>ssthresh时,停止使用慢开始算法,改用拥塞避免算法。
- 当cwnd=ssthresh时,既可以使用慢开始算法,也可以使用拥塞避免算法。
- 其中,拥塞避免算法的做法为,发送端的拥塞窗口cwnd每经过一个往返时延RTT就增加一个MSS的大小,通常表现为按线性规律增长。
无论在慢开始阶段还是拥塞避免阶段,只要发送方判断网络出现拥塞(超时),就把慢开始门限ssthresh设置为出现拥塞时的拥塞窗口的一半(但不能小于2)。然后把拥塞窗口重新设定为1,执行慢开始算法。
一个传输轮次:发送了一批报文段并收到它们的确认的时间/一个往返时延RTT/开始的发送一批拥塞窗口内的报文段到开始发送下一批拥塞窗口内的报文段的时间。
快重传和快恢复
快重传:首先要求接收方每收到一个失序的报文段后立即发出确认,让发送方及早知道有报文段没有到达接收方。发送方只要连续收到3个重复确认就立刻重传对方尚未收到的报文段。
快恢复算法:
- 当发送端收到连续3个重复的ACK,重新设置新的慢开始门限ssthresh=cwnd/2。
- 与慢开始不同的是拥塞窗口不是设置为1,而是和设置为新的慢开始门限ssthresh一样。
- 若发送窗口值还允许发送报文段,就按拥塞避免算法继续发送报文段。
应用层
DNS协议
如果说ARP协议是用来将IP地址转换为MAC地址,那么DNS协议则是用来将域名转换为IP地址(也可以将IP地址转换为相应的域名)。
DNS域名结构
域名的层次结构
域名系统必须要保持唯一性。为了达到唯一性的目的,因特网在命名的时候采用了层次结构的命名方法:
- 每一个域名都是一个标号序列(labels),用字母(A-Z, a-z,大小写等价)、数字(0-9)和连接符(-)组成。
- 标号序列总长度不能超过255个字符,它由点好分割成一个个标号(label)。
- 每个标号应该在63个字符之内,每个标号都可以看成一个层次的域名。
- 级别低的域名写在左边,级别高的域名写在右边。
域名服务主要是基于UDP实现的,服务器的端口号为53。
关于域名的层次结构,如下图所示:
举例:www.baidu.com
- com:一级域名,表示这是一个企业域名。同级的还有net(网络提供商),org(非盈利组织)等。
- baidu:二级域名,指公司名。
- www:万维网,只是一种习惯用法。
域名服务器
域名是分层结构,域名服务器也是对应的层级结构。
由高向低进行层次划分,可分为以下几大类:
分类 | 作用 |
---|---|
根域名服务器 | 最高层次的域名服务器,本地域名服务器解析不了的域名就会向其求助 |
顶级域名服务器 | 负责管理在该顶级域名服务器下注册的二级域名 |
权限域名服务器 | 负责一个区的域名解析工作 |
本地域名服务器 | 当一个主机发出DNS查询请求时,这个查询请求首先发给本地域名服务器 |
注:一个域名服务器所负责的范围,或者说由管理权限的范围,就称为区。
- 每个层的域名上都有自己的域名服务器,最顶层的是根域名服务器。
- 每一级域名服务器都知道下级域名服务器的IP地址。
- 为了容灾,每一级至少设置两个或以上的域名服务器。
域名解析过程
域名解析总体可分为以下过程:
- 输入域名后,先查找自己主机对应的域名服务器,域名服务器先查找自己数据库中的数据。
- 如果没有,就向上级域名服务器进行查找,以此类推。
- 最多回溯到根域名服务器,肯定能找到这个域名的IP地址。
- 域名服务器自身也会进行一些缓存,把曾经访问过的域名和对应的IP地址缓存起来,可以加速查找过程。
具体可描述如下:
- 主机先向本地域名服务器进行递归查询
- 本地域名服务器采用迭代查询,向一个根域名服务器进行查询
- 根域名服务器告诉本地域名服务器,下一次应该查询的顶级域名服务器的IP地址
- 本地域名服务器向顶级域名服务器进行查询。
- 顶级域名服务器告诉本地域名服务器,下一步查询权限服务器的IP地址。
- 本地域名服务器向权限服务器进行查询。
- 权限服务器告诉本地域名服务器所查询的主机的IP地址。
- 本地域名服务器最后把查询结果告诉主机。
上文我们提出了两个概念:递归查询和迭代查询
递归查询:本机向本地域名服务器发出一次查询请求,就静待最终的结果。如果本地域名服务器无法解析,自己会以DNS客户机的身份向其他域名服务器查询,直到得到最终的IP地址并告诉本机。
迭代查询:本地域名服务器向根域名服务器查询,根域名服务器告诉它下一步到哪里去查询,然后它再去查,每次它都是以客户机的身份去各个服务器查询。
DNS缓存
简单来说,一条域名的DNS记录会在本地有两种缓存:浏览器缓存和操作系统(OS)缓存。在浏览器中访问的时候,会优先访问浏览器缓存,如果未命中则访问OS缓存,最后再访问DNS服务器(一般由ISP提供),然后DNS服务器会递归式地查找域名记录,然后返回。
DNS记录会有一个TTL值,单位是秒,意思是这个记录最大有效期是多少。经过实验,OS缓存会参考TTL值,但是不完全等于。
而浏览器DNS缓存的时间跟TTL值无关,每种浏览器都使用一个固定值。
FTP协议
文件传输协议(FTP)作为网络共享文件的传输协议,在网络应用软件中具有广泛的应用。FTP的目标是提高文件的共享性和可靠高效地传送数据。
FTP是TCP/IP协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。由于FTP传输效率非常高,在网络上传输大的文件时,一般采用该协议。
默认情况下FTP协议使用TCP端口中的20和21这两个端口,其中20用于传输数据,21用于传输控制信息。但是,是否使用20作为传输数据的端口与FTP使用的传输模式有关,如果采用主动模式,那么数据传输端口就是20;如果采用被动模式,则具体最终使用哪个端口要服务器端和客户端协商决定。
工作方式
Port(主动模式)
FTP客户端首先和FTP服务器的21端口建立连接,通过这个通道发送命令,客户端需要接收数据的时候在这个通道上发送PORT命令。PORT命令包含了客户端用什么端口接收数据。在传送数据的时候,服务器端通过自己的TCP 20端口连接至客户端的指定端口发送数据。FTP服务器必须和客户端建立一个新的连接来传送数据。
Passive(被动模式)
在建立控制通道的时候和主动模式类似,但建立连接后发送的不是PORT命令,而是PASV命令。FTP服务器端收到PASV命令后,随机打开一个高端端口(端口号大于1024)并且通知客户端在这个端口上传送数据的请求,客户端连接FTP服务器此端口,通过三次握手建立通道,然后FTP服务器将通过这个端口进行数据的传送。
HTTP协议
HTTP协议(超文本传输协议)是用于从万维网服务器传输超文本到本地浏览器的传送协议。
HTTP是基于TCP/IP通信协议来传递数据的。
HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求,向客户端发送响应信息。
主要特点
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
- 灵活:HTTP允许传输任意类型的数据对象。
- 无连接:无连接的含义时限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。节省传输时间。
- 无状态:HTTP协议时无状态协议。无状态时指协议对事物处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。但另一方面,在服务器不需要先前信息时它的应答就较快。
- 支持B/S及C/S模式。
HTTP之请求消息Request
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:
请求行(request line)、请求头部(header),空行和请求数据四个部分组成。
第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本。
第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息。
从第二行起为请求头部,HOST将指出请求的目的地。User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础。该信息由浏览器来定义,并且在每个请求中自动发送等等。
第三部分:空行,请求头部后面的空行时必须的。
即使第四部分的请求数据为空,也必须由空行。
第四部分:请求数据,也叫主体,可以添加任意的其他数据。
这个例子的请求数据为空。
第一部分:请求行,第一行明了时POST请求,以及版本。
第二部分:请求头部,第二行至第六行。
第三部分:空行,第七行的空行。
第四部分:请求数据,第八行。
HTTP之响应消息Response
一般情况下,服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息。
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
第一部分:状态行,由HTTP协议版本号,状态码,状态消息三部分组成。
第二部分:消息报头,用来说明客户端要使用的一些附加信息。
第三部分:空行,是必须有的。
第四部分:响应正文,服务器返回给客户端的文本信息。
HTTP之状态码
状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
1xx:指示信息——请求已接收,继续处理。
2xx:成功——请求已被成功接收、理解、接受。
3xx:重定向——要完成请求必须进行更进一步的操作。
4xx:客户端错误——请求有语法错误或无法实现。
5xx:服务器端错误——服务器未能实现合法的请求。
HTTP请求方法
根据HTTP标准,HTTP请求可以使用多种请求方法。
HTTP1.0定义了三种请求方法:GET,POST和HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS,PUT,DELETE,TRACE和CONNECT方法。
GET ——请求指定的页面信息,并返回实体主体。
HEAD——类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头。
POST——向制定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST可能会导致新的资源的建立和/或已有资源的修改。
PUT——从客户端向服务器传送的数据取代指定的文档的内容。
DELETE——请求服务器删除指定的页面。
CONNECT——HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIOINS——允许客户端查看服务器的性能。
TRACE——回显服务器收到的请求,主要用于测试或诊断。
HTTP工作原理
HTTP请求/响应步骤:
- 客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。 - 发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。 - 服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源副本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。 - 释放TCP连接
若connection模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求。 - 客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML语法对其进行格式化,并在浏览器窗口中显示。
例如:在浏览器地址键入URL,按下回车之后会经历以下流程:
- 浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址。
- 解析出IP地址后,根据IP地址和默认端口80,和服务器建立TCP连接。
- 浏览器发出读取文件HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器。
- 服务器对浏览器请求做出响应,并把对应的HTML文本发送给浏览器。
- 释放TCP连接。
- 浏览器将该HTML文本解析并显示内容。
GET和POST请求的区别
- GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连。POST方法是把提交的数据放在HTTP包的Body中。
- GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
- GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。
- GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码。
HTTPS协议
HTTP+加密+认证+完整性保护=HTTPS
HTTPS是身披SSL外壳的HTTP:HTTPS并非是应用层的新协议,只是HTTP通信接口部分用SSL和TLS协议代替了而已。
通常,HTTP直接和TCP通信。当使用SSL时,则演变成先和SSL通信,再由SSL和TCP通信了。
HTTPS采用共享密钥加密和公开密钥加密两者并用的混合加密机制。
共享加密机制:加密解密使用相同的密钥。
公开密钥加密:由公开密钥和私有密钥协作。发送方发送数据时,用对方的公开密钥加密,接收方收到数据后,用自己的私有密钥解密。
如何解决公开密钥正确性问题:公开密钥由数字证书认证机构和其相关机构颁发证书来证明正确性。
HTTPS缺点:比HTTP慢2到100倍。在加密和解密运算上花费了太多时间。
TCP连接和释放时的常见问题
TCP为什么要三次握手,TCP为什么可靠
为什么不能两次握手:防止已失效的连接请求又传送到服务器端,因而产生错误。
假设改为两次握手,client端发送的一个连接请求在服务器滞留了,这个连接请求是无效的,client已经是closed的状态了,而服务器认为client想要建立一个新的连接,于是向client发送确认报文段,而client端是closed状态,无论收到什么报文都会丢弃。而如果是两次握手的话,此时就已经建立连接了。服务器此时会一直等到client端发来数据,这样就浪费掉很多server端的资源。
校注:此时因为client没有发起建立连接请求,所以client处于CLOSED状态,接收到任何包都会丢弃,谢希仁举的例子就是这种场景。但是如果服务器发送对这个延误的旧连接报文的确认的同时,客户端调用connect函数发起了连接,就会使客户端进入SYN_SEND状态,当服务器对延误旧连接报文的确认传到客户端时,因为客户端已经处于SYN_SEND状态,所以就会使客户端进入ESTABLISHED状态,此时服务器端反而丢弃了这个重复的通过connect函数发送的SYN包。而连接建立后,发送包由于seq是以被丢弃的SYN包的序号为准,而服务器接收序号是以那个延误旧连接SYN报文序号为准,导致服务器丢弃后续的数据包。
三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。
TCP可靠传输的实现:
TCP连接的每一端都必须设有两个窗口——一个发送窗口和一个接收窗口。TCP的可靠传输机制用字节的序号进行控制。TCP所有的确认都是基于序号而不是基于报文段。
发送过的数据未收到确认之前必须保留,以便超时重传时使用。发送窗口没收到确认不动,收到新的确认后前移。
发送缓存用来暂时存放:发送应用传给发送方TCP准备发送的数据;TCP已发送出但尚未收到确认的数据。
接收缓存用来暂时存放:按序到达的、但尚未被接收应用程序读取的数据;不按序到达的数据。
必须强调三点:
- A的发送窗口并不总是和B的接收窗口一样大(因为有一定的时间滞后)。
- TCP标准没有规定对不按序到达的数据应如何处理。通常是先临时存放在接收窗口中,等到字节流中所缺少的字节接收到后,再按序交付上层的应用进程。
- TCP要求接收方必须有累积确认的功能,这样可以减少传输开销(累积确认:一般讲,如果发送方发了包1,包2,包3,包4;接收方成功接收到包1,包2,包3。那么接收方可以发回一个确认报,序号为4(4表示期望下一个收到的包的序号;当然你约定好用3表示也可以),那么发送方就直到包1到包3都发送接收成功,必要时重发包4。一个确认报确认了累积到某一序号的所有包。而不是对每个序号都发确认报。)
为什么释放连接需要TIME_WAIT
TIMEWAIT状态也称为2MSL等待状态。
- 为实现TCP这种全双工连接的可靠释放。
为了保证A发送的最后一个ACK报文能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后就立即释放连接,就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。这样,B就无法按照正常的步骤进入CLOSED状态。 - 为使旧的数据包在网络因过期而消失。
A在发送完ACK报文段后,再经过2MSL时间,就可以使本连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段。
为什么建立连接是三次握手,而关闭连接确实四次挥手呢?
这是因为服务的在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了,但是还能接收数据,我们也未必全部数据都发送给对方了,所以我们不可以立即close。可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,我们的ACK和FIN一般都会分开发送。