为什么计算机网络要分层,有什么好处
1.各层次之间是独立的。某一层并不需要知道它的下一层是如何实现的,而仅仅需要知道该层通过层间的接口所提供的服务。这样,整个问题的复杂程度就下降了。也就是说上一层的工作如何进行并不影响下一层的工作,这样我们在进行每一层的工作设计时只要保证接口不变可以随意调整层内的工作方式。
2.灵活性好。当任何一层发生变化时,只要层间接口关系保持不变,则在这层以上或以下层均不受影响。当某一层出现技术革新或者某一层在工作中出现问题时不会连累到其它层的工作,排除问题时也只需要考虑这一层单独的问题即可。
3.结构上可分割开。各层都可以采用最合适的技术来实现。技术的发展往往不对称的,层次化的划分有效避免了木桶效应,不会因为某一方面技术的不完善而影响整体的工作效率。
4.易于实现和维护。这种结构使得实现和调试一个庞大又复杂的系统变得易于处理,因为整个的系统已经被分解为若干个相对独立的子系统。进行调试和维护时,可以对每一层进行单独的调试,避免了出现找不到、解决错问题的情况。
5.能促进标准化工作。因为每一层的功能及其所提供的服务都已有了精确的说明。标准化的好处就是可以随意替换其中的某一层,对于使用和科研来说十分方便。
为什么需要TCP协议
TCP实现网络中的可靠传输,工作在运输层,其功能包括重传(超时重传,快速重传),拥塞控制,流量控制,滑动窗口,差错检测。
TCP,UDP的头部格式
TCP报文段头部最少20个字节,最大60字节,可变长度(原端口,目的端口,首部检验和,六个标志位,序列号,确认号,fin,syn,ack,rst,窗口大小),UDP固定8字节(原端口,目的端口,头部检验和,头部+数据的总长度)
如何唯一确定一个TCP连接
四元组(原IP,原端口,目的IP,目的端口)
TCP最大连接数
端口数*IP地址数量
TCP和UDP的区别
首部长度不同,TCP面向字节流,一个字节一个字节发,UDP面向报文,一个报文一个报文发,UDP一般不分段,基本都比MSS小,防止出现一个错误全部重传,而且UDP也没有拥塞控制和流量控制,是不可靠传输。
为什么说TCP报文段是面向字节流的,UDP包是面向数据报的?
面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会使IP太小。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。
虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。
在TCP建立连接前两次握手的SYN报文中选项字段的MSS值,通信双方商定通信的最大报文长度。如果应用层交付下来的数据过大,就会对数据分段,然后发送;否则通过滑动窗口协议来控制通信双发的数据。
TCP三次握手
第一次:客户端将标识位的SYN置1,表示这是一个连接请求报文,生成一个随机序列号X,发送给服务器端。
第二次:服务器接收到客户端的请求连接,也生成一个随机序列号Y,将ACK和SYN置1,表示确认号有效,ack为X+1
第三次:客户端接收到服务器的应答报文,将SYN,ACK置1,ack为Y+1,第三次握手可以携带数据了。
为什么是3次握手
首先,假如是2次的话,客户端第一次发送一个序列号为100的请求,如果网络拥堵导致超时,服务器端没收到。客户端又重传了一个序列号为101的请求报文,这个时候序列号为100的报文又来到了服务器端并被接受了,导致服务器建立了一个过时的连接,而因为是2次握手,握手过程结束了,客户端开始发送消息,但是服务器端的ack和客户端发送的seq不一致,浪费了资源。
如果是3次的话就可以检测出这种错误,客户端可以根据第二次握手的ack号来确认服务器端是不是建立了一个过时的连接。
4次没必要,3次就能够保证安全的建立连接了。
四次挥手过程
客户端将FIN置为1,表示断开请求报文,服务器端接受到之后回应一个ACK报文,将ACK置1。然后服务器可能有数据没有处理完,有一个close_wait等待时间,数据处理完后,再发送一个FIN置1的报文给客户端,客户端回应一个ACK报文,然后等待2MSL再断开客户端的连接,服务器在收到第四次挥手的报文之后立刻断开连接。
为什么是4次挥手
因为服务端在收到客户端的FIN报文后,可能还有数据要处理和发送,这个时候不能马上断开,所以要把服务端的ACK和FIN分开发送。三次握手的时候,第二次握手把ACK和连接两次放一块了,断开不能放一块。
为什么TCP要分片MSS
因为一个TCP连接如果不分片的话,当数据报里面出现了错误,TCP会重传整个报文,浪费了资源,但是分片的话,只会重传出错的一片。
SYN攻击
服务器有一个SYN队列和一个accept队列,首先将请求置入到SYN队列,然后服务器发送回应报文,收到客户端的第三次握手报文之后,再将SYN请求放入accept队列,再由程序从accepy队列取出数据进行解析渲染。如果一个攻击人一直向服务器发送SYN请求报文,导致SYN队列总是满的,而且不回应服务器端的响应,导致服务器一直处于等待状态,而真正需要请求的客户端就请求不到数据。
为什么有close_wait和time-wait
前者:被动方收到请求断开连接方的FIN报文后可能还有数据没有处理完,需要等待数据处理完成再发送断开连接报文。这个等待时间就是close_wait
后者:第四次挥手之后,如果对方未接受到第四次挥手,就一直处于等待状态,不能及时断开浪费资源,而这个时候主动方又关闭了连接,无法重传第四次挥手。所以等待2MSL(一个报文在网络中的最大生存时间)如果超过2MSL还没有接收到错误信息,再关闭。
重传机制
实现这个功能基于发送-应答模式,服务器每次接受到数据之后会发送一个请求应答报文,通过应答报文可以实时检测发送数据的正确性。比如客户端发送了序列号1-100的字节,则服务器的ack的序列号应该为101,如果不是101则代表出现了差错,并进行重传。
超时重传:发送数据的时候设置一个定时器,当超过定时器的时间收不到应答报文的时候,进行重传。
RTT表示一个报文从一端到另一端的往返时间。
超时重传的定时器用RTO表示。
快速重传
不用时间来定义,用数据。
当客户端连续收到3个同样的应答报文之后触发。
缺点就是不知道重传哪一个,假如序列号2没收到,一直ACK序列号2,但是客户端不知道2之后的数据有没有收到,所以分不清到底重传2,还是2之后的全部序列。
SACK方法
接收方维护一个接收缓存,并且在应答头部选项字段加上这个缓存信息,这样发送方就能知道哪些数据没收到了。
DACK
滑动窗口
发送方每发送一个段数据就要应答一次效率实在太低,所以引入了这个滑动窗口,发送方可以每次发送滑动窗口长度里的数据而且不用等待应答可以接着发送,直到滑动窗口用完。
采用累积确认和累积应答模式,假如ACK100没收到,但是后来ACK200送到了,证明200之前的数据都收到了,只是ACK100超时了,不用重传。
窗口就像发送方的一个缓存区,收到一个确认就释放一个空间。
TCP头部有一个窗口大小的字段,接收方用来表示自己能接收多少数据,发送方就根据这个窗口大小来发送数据。所以发送窗口大小由接收窗口决定。
TCP使用三个指针来表示每个类别的字节数。
SND.WND:这个表示滑动窗口的大小:上图大小为20,32-51
SND.UNA:指向的是已发送的字节但还未收到确认所有字节的首位上图32
SND.NXT:指向未发送但是可以发送的字节的首位,上图46
可用窗口大小为:WND-(NXT-UNA)
接收窗口
接收窗口和发送窗口是约等于,因为滑动窗口是动态变化的。
接收窗口有两个指针,一个WND一个NXT,WND是大小,NXT是未接收到的字节序列号。
流量控制
拥塞控制(慢启动,拥塞避免,快恢复,快重传)
cwnd拥塞窗口,单位为MSS,先从1开始,每次乘2,到达门限制执行拥塞避免,门限和cwnd每次加1,如果超时执行快重传,门限除以2,cwnd置为1,重新慢开始。如果连续收到三个相同的确认,门限和cwnd除2,执行拥塞避免算法。