TCP/IP问答
TCP和UDP的区别?
- 两者都是传输层协议,TCP(Transmission Control Protocal),名称反应了它最大的特征,就是对传输过程有很好的控制,即面向连接、可靠的、面向字节流的协议,它可以实现差错控制、流量和拥塞控制。UDP(User Datagram protocal),用户数据报协议,名字反应了它的一大特征,基于用户数据报。
- TCP的所谓面向字节流,是对TCP来说,来自上层(应用程序)的每一段数据的大小其实无所谓,比如应用程序一次发了很长的一段数据,TCP可以根据实际的网络情况进行数据分段发送;或者应用程序只发了很小的数据,那么TCP可能在缓冲区中等待一会,到数据足够后再一次发送一个大一点的数据。而UDP的面向数据报,是说它不对应用层来的数据做任何切分或组合,而是直接加上UDP包头后交给IP层,如果数据过长,则有由IP层负责分片。
- 粘包问题:在基于TCP的应用程序中,应用层交给TCP的一段一段的数据,可能会被TCP经过切分后,在接收端将前一片的部分和后一片粘在一起,造成应用层解释出错。解决方法:可以在应用层数据添加完整数据包头,指示数据长度;或在发端采用TCP的push,接收端及时将缓冲区数据提交应用层。
TCP的差错控制、流量和拥塞控制如何实现?
- 差错控制通过确认(ack)实现。流量控制通过滑动窗口实现,该滑动窗口是一个虚拟的概念,主要由两个指标来动态维护:ack(确认序列号)影响窗口的左边沿,rwnd接收端窗口指示影响右边沿的移动。
拥塞控制主要由rwnd和cwnd以及慢启动、拥塞避免机制来实现,另外,为了进一步提高网络利用效率,还有快速重传和快速恢复算法。发送方控制拥塞的主要原则是:
只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。
该原则对应慢启动和拥塞避免(增大拥塞窗口)、快速恢复。
拥塞控制过程
- 在未检测出拥塞发生时,主要包括两个阶段:慢开始和拥塞避免。慢开始阶段,cwnd初始设置为1个mss,然后每收到一次ack就酱cwnd加1,直到超过ssthresh ,转而执行拥塞避免,拥塞避免阶段,cwnd呈线性增长。
- 当检测出拥塞发生时,即出现重复ack或者没有收到ack,前者说明之前发送的某个包丢掉了,这时配合快速重传算法,接收端需要立即发送重复的ack,以通知发送方尽早重发丢掉的包。当发送方接收到重复的三个ack后,会立即重传对应的包,这就是快速重传。配合的有快速恢复算法,即接收端不是立即执行慢开始算法,而是将ssthresh立即减半,然后将cwnd设置为ssthresh减半后的数值,之后执行拥塞避免算法。
持续更新……
04.02.2016
TCP握手为什么是三次,而不是两次,四次?
在面经里面看到有人被问到这个问题,想了一会感觉不知道怎么回答,只要求助google。
知乎这个问题的二楼我觉的回答到了点子上,再结合一楼的回答,我觉得能比较完整地回答这个问题,以下是搬运过来的:在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”,在另一部经典的《计算机网络》一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。
这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足”在不可靠信道上可靠地传输信息”这一需求所导致的。
举的一个例子场景是,client发送的请求在网络中滞留了,很长一段时间后才到大server端,这时server如果返回ack,如果client不用ack(不是三次握手)而server端直接认为连接建立的话,由于client此时真实没有请求,将导致server端资源白白浪费。这个回答解释了为什么要三次握手:不可靠的信道,可靠传输的需求。为什么是三次:三次是理论最小值。
第二个回答在不可靠信道背景下,直接解释了三次握手的原因,二次握手为什么不够:
(由于作者设置了转载权限,后面再转过来)
大概思路就是双方都要确认是否能够正常发信、收信。在client发出请求后,如果收到server的ack,表明client的收、发都是通的,但是server并不能得知(如果只有两次握手的话)自己的发信功能是否是通的,所以还需要client的ack。
所以这个问题总结起来就是两点:
- 不可靠信道上可靠传输的需求,导致了需要握手,三次握手是最小值(意味着三次以上肯定可以,但是不划算)。
- 为什么三次是最小值,因为双方都要确认收、发信是否可靠(以及是否同意通信)。
持续更新……