4. TCP/IP
TCP/IP是协议簇,包括两个协议集:TCP——传输控制协议(传输层),IP——互联网络协议(网络层)。
应用层中还包括DNS、HTTP等协议。
HTTP信息流动过程:
TCP/IP信息流动:
4.1 IP
提供无连接的数据报服务,进行路由选择。
数据报分为报头和数据区,报头包含源和目的的IP地址。有两种版本,IPv4和IPv6。
IP地址长32 bit。地址格式为:IP地址=网络地址+主机地址 或 IP地址=主机地址+子网地址+主机地址,五类不同的互联网地址格式如下:
4.2 ICMP
因特网控制信息协议,是一种差错报告机制,差错和拥挤时会通知源主机。不可靠。
①测试目的主机可达性和缓冲区大小;
②报告不可达目的主机;
③数据报流量控制;
④检测循环或超长路由;
⑤报告错误数据报头;
⑥获取网络地址。
【问题1】简述一下ping的原理?
答:如ping 192.168.0.5,ping就是给目标IP地址发送一个 ICMP 回显请求,并要求对方返回一个 ICMP 回显应答来确定两台网络机器是否连通,时延是多少。
在 ICMP 逐层封装的过程中,需要知道源IP、源MAC地址、目的IP、目的MAC地址,前三者是已知的,只需要获取目的MAC地址即可:若在同一网段,只需要发送ARP广播;若不在同一网段,发送ARP广播给交换机,交换机若没有缓存目的IP对应的MAC地址,它会再转发该ARP广播包。
【问题2】traceroute命令有什么作用?原理是什么?
答:追踪从本机到指定主机的路由途径。traceroute程序是利用 ICMP 及 IP 头部的 TTL(存活时间)来实现其功能的。
每当数据包经过一个路由器,其存活时间就会减1。当其存活时间是0时,主机便取消数据包,并回复一个「ICMP time exceeded」数据包给发出者。首先,traceroute发送一个TTL为1的数据包到目的地,当路径上的第一个路由器收到这个数据包时,将它的TTL减1。此时,TTL变为0了,所以该路由器会将此数据包丢掉,并送回一个「ICMP time exceeded」消息,traceroute 收到这个消息后,便知道这个路由器存在于这个路径上。接着traceroute 再送出另一个TTL是2 的数据包,发现第2个路由器…… traceroute 每次将送出的数据包的TTL加1来发现另一个路由器,这个重复的动作一直持续到数据包抵达目的地。
当数据包恰好抵达目的地时,由于traceroute所设置的端口是一个一般应用程序都不会用的号码,所以该主机会回送一个「ICMP port unreachable」的消息,而当traceroute 收到这个端口不可达的ICMP消息时,便知道目的地已经到达了。
4.3 ARP和RARP
ARP(Address Resolution Protocol):IP-->MAC,只适用于广播功能的网络,如以太网。
RARP(Reverse Address Resolution Protocol):MAC-->IP
4.4 IPv6
①扩大了选址能力:IP范围由32位增加到128位
②简化了分组头格式:删除了一些字段
③改善了扩展与选项:特别编码增加传输高效性,可变字段
④增加标签能力,如表示实时服务
⑤加入审计与保密能力:各种安全选项,如审计、完整性、保密性。
4.5 TCP
面向连接,把字节流分割成离散的报文传送给IP层。IP层不能保证报文传输正确,由TCP进行超时,重传控制。
- SYN,表示建立连接
- FIN,表示关闭连接
- ACK,表示响应
- PSH,表示有DATA传输
- RST,表示连接重置
- URG,表示紧急比特
三次握手
3次握手才能形成一个闭环,TCP本身是个双向链接,需要对服务端进行资源保护,只有3次握手才能形成一个完整可靠的闭环。
四次挥手
连接释放的状态
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:“三次握手”的主要目的是为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
例如:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送ack包。
“四次挥手”主要是为了确保数据能够完成传输。
因为TCP连接是全双工的(即数据可在两个方向上同时传递),关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
滑动窗口
由于是全双工协议,因此发送方和接收方应该分别维护着一个独立的发送缓冲区和接收缓冲区。
对于乱序的分组则先接收下来,避免网络重复传递(选择重发)。
回退N帧的滑窗协议:接收方丢弃错帧后的所有帧,发送方收到否定应答后(NAK)重发错帧后的所有数据帧。
选择重发滑窗协议:错帧后的正确帧先缓存下来,同时要求发送方重传错帧,收到后与缓存中的其余帧一起按正确顺序发送至主机。
流量控制
1)TCP中的流量控制通过可变大小的滑动窗口来处理的。
接收方传递信息给发送方,使其不要发送数据太快,返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。
2)传输效率
a、为了避免发送大量的小数据包,尽可能一次多发送几个字节,我们广泛使用Nagle算法,即:
*1. 若发送应用进程要把发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面的字节先缓存起来;
*2. 当发送方收到第一个字节的确认后(也得到了网络情况和对方的接收窗口大小),再把缓冲区的剩余字节组成合适大小的报文发送出去;
*3. 当到达的数据已达到发送窗口大小的一半或以达到报文段的最大长度时,就立即发送一个报文段;
b、窗口空余较多的时候通知发送方一次发送多个字节:
让接收方等待一段时间,或者接收方获得足够的空间容纳一个报文段或者等到接受缓存有一半空闲的时候,再通知发送方发送数据。
【问题1】如果接收端处理缓慢,导致发送方的滑动窗口变为0了,怎么办?
答:这时发送端就不发数据了,但发送端会发ZWP(即Zero Window Probe技术)的包给接收方,让接收方回ack更新Window尺寸,一般这个值会设置成3次,每次大约30-60秒。如果3次过后还是0的话,有的TCP实现就会发RST把连接断了。
拥塞控制
发送方维持一个叫做“拥塞窗口”的变量,该变量和接收端口共同决定了发送者的发送窗口。
在开始时设置拥塞窗口大小(cwnd) 为一个最长段长度(MSS),每次接到一个确认时,窗口的大小就增加一个MSS值。
RTO:超时重传机制(Retransmission Timeout),为了防止数据报丢失,当TCP发送一个报文时,就启动重传计时器,有2种情况:
【慢启动】
-1. 当主机开始发送数据时,避免一下子将大量字节注入到网络,造成或者增加拥塞,选择发送一个1 MSS的试探报文;
-2. 当收到第一个MSS的数据的确认后,就发送2 MSS的报文;
-3. 若再次收到2个MSS的确认,则发送4 MSS字节,依次递增2的指数级;
-4. 最后会达到一个提前预设的“慢启动门限”,比如24,即一次发送了24个分组,此时遵循下面的条件判定:
*1. cwnd < ssthresh, 继续使用慢启动算法;
*2. cwnd > ssthresh,停止使用慢启动算法,改用拥塞避免算法;
*3. cwnd = ssthresh,既可以使用慢启动算法,也可以使用拥塞避免算法;
【拥塞避免】
每经过一个往返时间RTT就把发送方的拥塞窗口+1,即让拥塞窗口缓慢地增大,按照线性规律增长;
【拥塞发生】
①RTO超时,那么存在非常严重的拥塞的可能性,比如丢包时,图5-25
将慢启动门限设为原先的一半,然后将cwnd设为1,执行慢启动算法(较低的起点,指数级增长);
②如果收到3个相同的ACK,那么存在着轻度拥塞的可能性,图5-27,快速重传
*1. 慢启动门限减半;
*2. cwnd设为慢开始门限减半后的数值;
*3. 执行拥塞避免算法(高起点,线性增长);
【快速恢复】
“快速恢复”算法是在“快速重传”算法后添加的,当收到3个重复ACK时,TCP最后进入的不是拥塞避免阶段,而是快速恢复阶段。
快速恢复状态是一种介于慢启动和拥塞避免之间的状态。
*1. 慢启动门限减半;
*2. cwnd = sshthresh + 3 * MSS (加3的原因是因为收到3个重复的ACK,表明有3个“老”的数据包离开了网络)
*3. 重传丢失报文段
*4. 再收到重复的ACK时,拥塞窗口增加1
*5. 收到新的数据包的ACK时,把cwnd设置为第1步中的ssthresh的值,再次进入拥塞避免状态。(如果在此过程出现超时,则重新进入慢启动)
4.6 UDP
无连接,不可靠,在C/S的请求响应模式中使用广泛。
【问题1】TCP 和 UDP 的区别?
答:TCP是稳定、可靠、面向连接的传输层协议,它在传递数据前要三次握手建立连接,在数据传递时,有确认机制、重传机制、流量控制、拥塞控制等,可以保证数据的正确性和有序性。UDP是无连接的数据传输协议,端与端之间不需要建立连接,且没有类似TCP的那些机制,会发生丢包、乱序等情况。TCP是数据流模式,而UDP是数据报模式。
【问题2】为什么 TCP 叫数据流模式? UDP 叫数据报模式?
所谓的“流模式”,是指TCP发送端发送几次数据和接收端接收几次数据是没有必然联系的,比如你通过 TCP 连接给另一端发送数据,你只调用了一次 write,发送了100个字节,但是对方可以分10次收完,每次10个字节;你也可以调用10次 write,每次10个字节,但是对方可以一次就收完。
原因:这是因为TCP是面向连接的,一个 socket 中收到的数据都是由同一台主机发出,且有序地到达,所以每次读取多少数据都可以。
所谓的“数据报模式”,是指UDP发送端调用了几次 write,接收端必须用相同次数的 read 读完。UDP 是基于报文的,在接收的时候,每次最多只能读取一个报文,报文和报文是不会合并的,如果缓冲区小于报文长度,则多出的部分会被丢弃。
原因:这是因为UDP是无连接的,只要知道接收端的 IP 和端口,任何主机都可以向接收端发送数据。 这时候, 如果一次能读取超过一个报文的数据, 则会乱套。
参考:http://blog.chinaunix.net/uid-26275986-id-4109679.html
http://blog.csdn.net/whuslei/article/details/6667471
http://blog.csdn.net/kzq_qmi/article/details/46940463
《计算机网络》 邮电出版社
《图解HTTP》