经历了残酷的秋招之后,我总结了全面的TCP/IP面试知识点
计算机网络知识点
- OSI七层模型
- 计算机网络的五层协议体系结构
- TCP(传输控制协议)的主要特点
- TCP协议选项:
- 标志位的含义
- UDP(用户数据报协议)的主要特点
- TCP和UDP的区别
- TCP和UDP的应用场景:
- 如何使UDP实现可靠传输?(基于自动重传请求ARQ的实现)
- 为什么说UDP比TCP更有优势?
- 为什么像即时通讯会选用UDP?而不是采用TCP进行实现?
- 什么是连续ARQ协议?
- TCP如何保证可靠传输?
- 什么是超时重传?
- 什么是滑动窗口,实现原理?
- TCP的流量控制:
- 拥塞控制
- TCP状态转换图
- 聊一聊TCP三次握手
- 什么是SYN攻击?
- 谈谈TCP的四次挥手。
- 除了时间等待计时器外,TCP还设有一个保活计时器是干什么的?
- 如何提高TCP的传输效率?
- 粘包问题?怎样避免?
- TCP协议有几大计时器?
OSI七层模型 OSI七层模型的各层功能:
1.物理层:传输比特流。
2.数据链路层:提供介质访问和链路管理。完成封装成帧,透明传输,差错检测。
3.网络层:IP选址和路由选择。
4.传输层:建立,管理和维护端到端的连接。
5.会话层:建立,管理和维护会话
6.表示层:进行数据格式转换,数据加密
7.应用层:为应用程序提供服务。
文章图片
计算机网络的五层协议体系结构
- 应用层:应用层是体系结构中的最高层。应用层的任务是通过应用进程之间的交互来完成特定网络应用。向用户提供常用的应用程序服务,比如电子邮件,文件传输访问,远程登录等。远程登录TELNET使用TELNET协议提供在网络其它主机上注册的接口。TELNET会话提供了基于字符的虚拟终端。文件传输访问FTP协议来提供网络内机器间的文件拷贝功能。应用层一般是面向用户的服务。如FTP,TELNET,DNS,SMTP,POP3.
FTP是文件传输协议,一般上传和下载用FTP服务,数据端口为20H,控制端口为21H.
TELNET服务是用户远程登录服务,使用23H端口,使用明码传送,保密性差,但简单方便。
DNS是域名解析服务,提供域名到IP地址之间的转换。
SMTP是简单邮件传输协议,用来控制信件的发送、中转。
POP3是邮局协议第3版本,用于接收邮件。
- 运输层:运输层的任务就是负责两台主机中进程之间的通信提供通用的数据传输服务。网络层是点到点的传输(主机或路由器),而运输层负责端到端(源主机和目的主机)的传输。(通用指的是多种应用可以使用同一个运输层服务)
功能包括:
一、格式化信息流。
二、提供可靠传输。为实现可靠传输,传输层协议规定接收端必须发回确认,并且假如分组丢失,必须重新发送。
- 网络层:负责为分组交换网上的不同主机提供通信服务(逻辑通信)。网络层把运输层产生的报文段或用户数据报封装成分组(IP数据报)或包进行传送,另一个任务是选择合适的路由,使源主机运输层传下来的分组,能够通过网络中的路由器找到目的主机。
文章图片
- 数据链路层:将网络层交下来的IP数据报分装成帧,在两个相邻的节点链路上传输帧。每一帧包括数据和必要的控制信息。
三个基本问题:
封装成帧:在一段数据的前后分别加上首部和尾部,就构成了一个帧。
透明传输:表示无论什么样的比特组合的数据,都能够按照原样没有差错的通过这个数据链路层。
差错检测:比特在传输过程中可能会产生差错,因此必须采用各种差错检测措施。目前广泛使用循环yun余校验
文章图片
TCP(传输控制协议)的主要特点
- 物理层:传输比特流。
(1)面向连接。TCP协议选项:
(2)每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。
(3)提供可靠交付的服务。
(4)提供全双工通信。
(5)面向字节流。(指的是虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一串无结构的字节流,TCP并不知道字节流的含义)
- TCP报文:
文章图片
1.TCP_NODELAY 选项,可以关闭Nagle算法。标志位的含义
2.窗口扩大选项可以扩大窗口
3.时间戳选项,可以计算超时重传往返时间。
URG:指示报文中有紧急数据,应尽快传送(相当于高优先级的数据)。UDP(用户数据报协议)的主要特点
PSH:为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
RST:TCP连接中出现严重差错(如主机崩溃),必须释放连接,在重新建立连接。
FIN:发送端已完成数据传输,请求释放连接。
SYN:处于TCP连接建立过程。 (Synchronize Sequence Numbers)
ACK:确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。
(1)UDP是无连接的。TCP和UDP的区别
(2)尽最大努力交付,但不保证可靠交付
(3)面向报文(发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界)
(4)没有拥塞控制。
(5)支持一对一,一对多和多对多的交互通信。
(6)首部开销小,只有8个字节。
- udp报文:
文章图片
1.TCP面向连接(如打电话要先拨号建立连接)。UDP是无连接的,即发送数据之前不需要建立连接。TCP和UDP的应用场景:
2.TCP提供可靠的服务;UDP尽最大努力的交付,即不保证可靠交付。TCP通过检验和,重传机制,序号标识,滑动窗口,确认应答实现可靠传输。如丢包时的重传控制,还可以对次序乱掉的分包进行顺序控制。
3.UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性较高的通信或广播通信。但TCP会有延时,实时性差。
4.每一条的TCP连接只能是点对点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
5.TCP对系统资源要求较多,UDP对系统资源要求较少。
6.在传输相同大小的数据时,TCP的首部开销是20字节;UDP的首部开销是8个字节,所以TCP比UDP的的报头更复杂,实际传输的数据更少一些。
7.TCP的逻辑通信是全双工可靠信道,UDP是不可靠信道。
8.TCP是面向字节流的,实际上是TCP把数据看成一连串的无结构的字节流;UDP是面向报文的。
我们知道TCP数据传输可靠但传输速度慢,实时性差,延时高,UDP传输尽最大努力交付,数据传输不可靠但速度快,实时性好。如何使UDP实现可靠传输?(基于自动重传请求ARQ的实现)
所以如果在数据的完整性上有要求,则选用TCP协议(如文件传输、重要状态的更新);反之,对实时性高,要求数据的传输速度上,选用UDP(如视频传输,实时通信)
UDP应用场景:
1.面向数据报方式
2.网络数据大多为短消息
3.拥有大量Client
4.对数据安全性无特殊要求
5.网络负担非常重,但对响应速度要求高。
传输层无法保证数据可靠传输,只能通过应用层来实现。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。为什么说UDP比TCP更有优势?
不考虑拥塞控制处理,可靠UDP的简单设计:
(1)添加seq/ack机制,确保数据发送到对端。
(2)添加发送和接受缓冲区,主要用于用户的超时重传。
(3)添加超时重传机制。
详细说明:发送端发送数据时,生成一个随机的seq=x,然后每一片按照数据大小分配seq。当发送端发送完一个分组后,必须暂时保存分组的副本。数据到达接收端之后进入接收端缓存,并发送一个ack=x的包,表示对方已经收到了数据。发送方收到确认之后,删除缓冲区对应的副本。如果发送方在设定超时重传的时间内没有收到确认,就重传这个分组。
UDP以其简单、传输快的优势,在越来越多的场景下取代了TCP,如实时游戏。为什么像即时通讯会选用UDP?而不是采用TCP进行实现?
(1)网速的提升给UDP的稳定性提供了可靠的网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。
(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。
(3)采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接受到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包发生的延迟降到最低,尽量减少网络问题对游戏等应用造成影响。
因为UDP的端口通信机制。TCP连接的端口一般是有限的,而即时通讯,向视频转播需要对很多人进行视频的转发,而TCP的端口是不够的,UDP可以一对一,一对多。什么是连续ARQ协议?
文章图片
位于发送窗口内的5个分组都可以连续发送出去,而不需要等待对方的确认,这样信道的利用率就提高了。TCP如何保证可靠传输?
接收方一般都是采用累积确认的方式。这就是说:接收方不必对收到的分组逐个发送确认,而是在收到几个分组之后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已经正确收到了。
优缺点:
优点:易于实现,即使确认丢失也不必重传。
缺点:不能向发发送方反映出接收方已经正确收到的所有分组信息。
1.校验机制什么是超时重传?
校验和,占两个字节,16位。检验和字段检验的范围包括首部和数据两部分。
2.确认应答与序列号。
序列号:在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。
确认应答:TCP传输过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送ACK报文。这个报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次数据从哪里发。
3.超时重传:
Tcp的发送方在规定的时间内没有收到确认就要重传已发送的报文段。
4.流量控制(滑动窗口机制)
当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。
5.拥塞控制:
当网络拥塞时,减少数据的发送。
Tcp的发送方在规定的时间内没有收到确认就要重传已发送的报文段。什么是滑动窗口,实现原理?
问题:发送方发送出一个报文段,设定的重传时间到了,还没有收到确认。于是重传报文段。经过一段时间后,收到了确认报文段。现在的问题是:如何判定此确认报文段是对先发送的报文段的确认,还是对后来重传的报文段的确认?
方法是:报文段每重传一次,就把超时重传时间RTO增大一些。典型的做法是取新的重传时间为旧的重传时间的2倍。当不再发生报文段的重传时,才根据正确的公式计算超时重传时间。
为什么要使用滑动窗口?
因为为了提高传输效率,发送方可以连续的发送多个分组,不必每发完一个分组就停下来等接收方的确认。实现流水线传输方式,获得高的信道利用率。比如说,在收到0号报文的确认前还发送了1-3号报文,这样提高了信道的利用率。但这些报文有可能会丢失发生重传,所以需要一个缓冲区维护这些报文,就有了窗口。滑动窗口的实现原理?
文章图片
发送窗口:
发送窗口根据什么来构造?
根据接收窗口的报文段中的窗口和确认号。假定A收到了B发来的确认报文段,窗口大小为20字节,而确认号为31.(这就表明B期望收到的下一个序号是31,而序号30为止的数据都已经收到了)。
文章图片
发送窗口表示:在没有收到接受窗口的确认的情况下,发送窗口可以连续的把窗口内的数据发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。
要描述一个发送窗口的状态需要三个指针:P1,P2,P3 。指针都指向字节的序号。
P3-P1=A的发送窗口。
P3-P2=允许发送但尚未发送的字节数。
P2-P1=已发送但未收到确认的字节数。
当指针P1与P2重合时,窗口中都是允许发送但尚未发送的字节数。
当指针P2与P3重合时,发送窗口内的序号已用完,但还没有再收到确认。由于发送窗口已满,可用窗口减小到零,必须停止发送。
接收窗口:
接收窗口的大小取决于应用(比如说tomcat:8080端口的监听进程)、系统、硬件的限制。
文章图片
后方表示已发送确认并向主机交付。
黑色表示已收到收到的,白色表示允许接收但还未收到的数据。
假定B收到了序号为31的数据,并把序号为31~33的数据交付给主机,然后B删除这些数据,把接收窗口向前移动3个序号,同时给A发送确认,窗口大小仍然为20,但确认号为34.
A的p1指针向前移3个数据,p2不变,p3也向前移3个数据,表明A的可用窗口增大了。
TCP的流量控制:
利用滑动窗口实现流量控制
所谓的流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。是一个点对点通信量的控制,端到端的问题。
文章图片
简单来说就是,接收方处理不过来数据的时候,把窗口缩小,并把窗口值告诉发送方。
在连接建立时,B告诉A:我的接收窗口rwnd=400,因此发送方的发送窗口不能超过接收方给出的接收窗口的数值。
问题: 有这样一种情况,B向A发送零窗口报文段不久之后,B的接收缓存又有了一些空间。于是B向A发送rwnd=400的报文段,但是报文丢失,A一直等B,B也会一直等A,陷入死锁?
解决的办法是:当窗口值为0时,就启动TCP连接的持续计数器,若时间超过设置的时间,就发送一个零窗口探测报文段,而对方在确认这个探测报文段时给出现在的窗口值。如果仍然是0,就重新设置持续计数器,一段时间后重新发送探测。拥塞控制
所谓的拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至过载。前提是,网络能够承受的现有的网络负荷。
方法:
判断网络拥塞控制的依据就是出现了超时。
慢开始:当主机开始发送数据时,由于并不清楚网络的负荷情况,所以如果立即把大量的数据字节注入到网络中的话,就有可能引起网络发生拥塞。较好的方法是先探测一下,由小到大逐渐增大拥塞窗口数值。为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量,用法如下:
cwnd=min(rwnd,cwnd)
rwnd为通告窗口是接收方使用的流量控制,cwnd是发送方的拥塞窗口。
过程:当与一个网络的主机建立TCP连接时,拥塞窗口被初始化为1个报文段。每收到一个ACK,拥塞窗口就增加一个报文段。发送方取拥塞窗口与通告窗口中的最小值作为发送上限。发送方开始发送一个报文段,然后等待ACK。当收到该ACK时,就将拥塞窗口从1增加到2,即可发送两个报文段,当收到这两个报文段的ACK之后,就将拥塞窗口调至为4.这是一种指数增长的关系。
当cwnd 当cwnd>ssthresh时,使用拥塞避免算法。
当cwnd==ssthresh时,两者都可使用。
拥塞避免算法:
算法思路:是让拥塞窗口cwnd缓慢的增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是像慢开始算法那样加倍增长。因此在拥塞避免阶段就有“加法增大”的特点,在这个阶段拥塞窗口cwnd按线性规律缓慢增长。
文章图片
一般慢开始和拥塞避免算法是一起实现的,基本过程如下:
快重传和快恢复的提出:
- 当cwnd,也就是拥塞避免窗口
- 当cwnd=ssthresh慢开始门限时,就改为执行拥塞避免算法,拥塞窗口按线性规律增长,每次加1,使网络不容易出现拥塞。
- 当网络发生超时,发送方判断发生了拥塞,于是调整门限值为当前窗口的一半,将cwnd设置为1,重新执行慢开始算法。
- 当cwnd超过门限时,执行拥塞避免算法,拥塞窗口按线性增大。
这是数据丢包导致错误启动慢开始的一种修补机制。
快重传:
有这么一种情况:个别报文段在网络中丢失,但网络实际并未阻塞。但发送方迟迟收不到确认就会产生超时,误认为网络拥塞,错误开启慢开始算法。
所以这种情况下采用快重传算法:可以让发送方尽早知道个别报文段的丢失。
什么意思呢?
意思就是一旦有报文丢失,接收方没有收到某个报文时,不要等发送方给他发送报文时才捎带确认,而是要立即发送确认。只要发送方收到三个重复确认的报文,就知道接收方确实没有收到某个报文,立即重传,这样就不会误认为网络拥塞。快恢复是什么鬼呢?
如果出现连续三个ACK报文的确认,我们就知道不是网络拥塞而是报文丢失。于是不启动慢开始而是快恢复,立刻调整门限值ssthresh=cwnd/2=8,同时设置拥塞窗口cwnd=ssthresh,并开始执行拥塞避免算法。TCP状态转换图
文章图片
聊一聊TCP三次握手
文章图片
过程:
一开始两端的TCP进程都处于CLOSED状态。问题: 当B收到A的确认之后,也进入ESTABLISHED状态。
A主动打开连接,B被动打开连接。
B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的连接请求,然后服务器进程就处于LISTEN状态,等待客户的连接请求。
(1)第一次握手:A的TCP客户进程也是首先创建传输控制块TCB。然后向B发出连接请求报文段,(首部的同步位SYN=1,初始序号seq=x),SYN=1不携带数据但要消耗一个序号,此时TCP进入SYN-SENT(同步已发送状态)。
(2)第二次握手:B收到连接请求报文段后,如同意建立连接,则向A发送确认,在确认的报文段中(SYN=1,ACK(确认标志)=1,确认号ack=x+1,初始序号seq=y),(这个报文段也不能携带数据,但同样消耗一个序号),测试TCP服务器的进程进入SYN-RCVD(同步收到状态)。
(3)第三次握手:TCP客户进程收到B的确认之后,要向B给出确认报文段(ACK=1,确认号ack=y+1,序号seq=x+1).ACK报文段可以携带数据,但如果不携带数据则不消耗序号。TCP连接已经建立,A进入ESTABLISHED(已建立连接)。
为什么A还要发送一次确认呢?即二次握手不行吗?
这主要是为了防止已失效的连接请求突然又传送到B。什么是SYN攻击?
如果是两次握手,假定出现这样一种异常情况:A发出的第一个连接请求报文段并没有丢失,而是在某个网络节点长时间的滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求的报文段之后,就误认为是A又一次新的连接请求。于是向A发送确认报文段,同意建立连接。现在是二次握手,连接已经建立。但A呢?没有发送建立连接的请求也就不会理踩B,所以B的许多资源就浪费掉了。
在三次握手中,server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接,此时server处于SYN_RCVD状态,当收到客户端的ACK报文之后就进入ESTABLISHED状态。
syn攻击就是在client端短时间伪造大量的不存在的ip地址,并向sever不断发送SYN包,server对其进行回复,并等待确认。这些伪造的SYN连接长时间占用未连接队列,导致正常请求因为队列满而无法进行连接请求,引起网络拥塞。
检测方法:netstat -nap| grep SYN_RECV
谈谈TCP的四次挥手。
文章图片
(1)A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1(终止等待1)状态,等待B的确认。问题:为什么A在TIME-WAIT状态必须等待2MSL的时间呢?
(2)B收到连接释放报文段之后即发出确认报文段,(ACK=1,确认号ack=u+1,序号seq=v),B进入CLOSE-WAIT(关闭等待状态),此时TCP处于半关闭状态,A收到B的连接释放。
(3)A收到B的确认后,进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
(4)B没有向A发出的数据,B发出连接释放报文段(FIN(结束标志)=1,ACK=1,序号seq=w,确认号ack=u+1),B进入LAST-ACK(最后确认)状态,等待A的确认。
(5)A收到B的连接释放报文段之后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),A进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,A才进入CLOSED状态。
这有两个理由。问题:服务器端口大量处于close_wait是什么原因?
- 第一,为了保证A发送的最后一个ACK报文段能够到达B。
(这个ACK报文段可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B会重传FIN+ACK这个报文段,而A就能在2MSL时间内收到重传报文段。接着A重传一次确认,重新启动2MSL计时器,能保证A和B都能进入CLOSED状态。如果不等待,则A进入CLOSED状态,B无法收到ACK报文段,也无法重传,就不能按照正常步骤进入CLOSED状态)。- 第二,防止已失效的连接请求报文段。
(A在发送完最后一个ACK报文段之后,再经过2MASL,就可以使本连接持续时间内所产生的所有报文段都从网络中消失,就可以使下一次连接持续的时间内不会出现这种旧的连接请求报文段)。
所以说,虽然按道理四个报文都发送完毕了,但我们必须假设网络是不可靠的,可能会丢失报文。所以,等待2MSL是为了防止报文丢失,之后重发。
分析原因:首先colse_wait出现的时刻在一方首先发起链接释放报文之后,协议栈进行自动处理。如果之后没有继续发送FIN包和ACK包的话,会一直在Close_wait状态。问题:time_wait占用哪些资源?如何避免time_wait状态?
主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下,errno,如果不是EAGIN(read是非阻塞事件,如果事件没有发生就返回EAGIN),就断开连接。
在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接.这个场景下会出现大量socket处于TIME_WAIT状态.
造成的资源浪费:
*
短时间内占用大量端口,而端口之后0-65535的范围,并不是很多.别的请求过来后,分配不了socket,没有空闲端口供TCP连接.
如何避免:问题:为什么连接时是三次握手,关闭的时候却是四次握手?
可以使用setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))
设置SO_REUSEADDR套接字来修改内核参数,快速回收被关闭的socket,从而使TCP连接根本就不进入TIME_WAIT状态.
TCP是全双工的,它允许两个方向的数据传输被独立关闭.当主动发起关闭的一方关闭连接报文后,服务器对其进行确认,此时进入半关闭状态,只关闭了客户端的输出流连接但是服务器端可能还有数据没有发完.除了时间等待计时器外,TCP还设有一个保活计时器是干什么的?
只有当服务器端的数据发完,服务端也发送连接释放报文,相应的客户端需要对其进行确认收到了这个连接释放报文.所以一共是四次而不是三次
如何提高TCP的传输效率?
- 设想有这样的情况:客户已主动与服务器建立了TCP连接。但后来客户端的主机突然出现故障。显然,服务器以后就不能再收到客户发来的数据。因此,应当有措施使服务器不能白白的等待下去。这既是保活计时器。
- 服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常就是两个小时。若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔分钟发送一次。若一连发送10个探测报文段后仍然无客户的响应,服务器就认为客户端出了故障,接着就关闭了这个连接。
(1)捎带确认的方式。(因为发送一个字符就要加上字节的TCP首部和20字节的IP首部)粘包问题?怎样避免?
(2)Nagle算法。(把要发送的数据进行缓存,先发送第一个数据字节进行试探,只有收到对第一个数据字符的确认之后,再把发送缓存中的数据组装成报文段发送;当数据到达发送窗口大小的一半或已经达到报文段的最大长度时,就立即发送一个报文段。这样做,就可以有效提高网络的吞吐量).
(3)解决糊涂窗口综合征。
可以让接收方等待一段时间, 使得接受缓存已有足够的空间容纳一个最长的报文段,或者等到接收缓存已有一半空闲的空间。
(糊涂窗口综合征就是接收方仅腾出一个空间就给发送方发送确认,使网络效率低下).
原因:UDP没有使用合并优化算法,且支持一对多的模式,接收端是此采用了链式结构来接收UDP包,所以很容易就能区分处理。
(1)发送方而言:因为提高TCP的传输效率,使用了Nagle算法,将多次间隔较小,数据量小的数据合并成了一个大的数据块,然后进行封包,再发送出去。具体是这样的,(1)只有上一个分组得到确认,它才会发下一个分组。(2)收集多个分组,在一个确认到来时会一起发送。
(2)接收方而言:接收方不及时接收缓冲区的包,造成多个包接收。
这是因为接收方把收到的数据放在系统的缓冲区中,用户进程从中取数据,但是下一包数据到来前一包数据尚未被用户进程取走,则下一包数据就放到了缓冲区中前一包数据的后面,而用户从之前预先设定的缓冲区中取数据,就一次取到了多包。
怎样避免粘包现象措施?
发送而言:TCP协议有几大计时器?
1.关闭Nagle算法,使用TCP_NODELAY选项关闭nagle算法。
怎样分开?解决TCP无保护消息边界:
(1)发送固定长度消息
(2)把消息的尺寸与消息一块发送
(3)使用特殊标记作为消息之间的间隔
比较周全的对策是:接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开。
【经历了残酷的秋招之后,我总结了全面的TCP/IP面试知识点】四大计时器。
- 重传计时器
在一个TCP连接中,TCP每发送一个报文段,就对此报文段设置一个超时重传计时器。若在收到了对此特定报文段的确认之前计时器截止期到,则重传此报文段,并将计时器复位。- 持续计时器
为了对付零窗口大小通知,TCP需要另一个计时器。假定接收TCP宣布了窗口大小为零。发送TCP就停止传送报文段,直到接收TCP发送确认并宣布一个非零的窗口大小。但这个确认可能会丢失。我们知道在TCP中,对确认是不需要发送确认的。若确认丢失了,接收TCP并不知道,而是会认为它已经完成任务了,并等待着发送TCP接着会发送更多的报文段。但发送TCP由于没有收到确认,就等待对方发送确认来通知窗口的大小。双方的TCP都在永远地等待着对方。要打开这种死锁,TCP为每一个连接使用一个坚持计时器。当发送TCP收到一个窗口大小为零的确认时,就启动坚持计时器。当坚持计时器期限到时,发送TCP就发送一个特殊的报文段, 叫做 探测报文段 。这个报文段只有一个字节的数据。它有一个序号,但它的序号永远不需要确认;甚至在计算对其他部分的数据的确认时该序号也被忽略。探测报文段提醒对端:确认已丢失,必须重传。- 保活计时器
保活计时器使用在某些实现中,用来防止在两个TCP之间的连接出现长时期的空闲。假定客户打开了到服务器的连接,传送了一些数据,然后就保持静默了。也许这个客户出故障了。在这种情况下,这个连接将永远地处理打开状态。- 时间等待计时器
时间等待计时器是在连接终止期间使用的。当TCP关闭一个连接时,它并不认为这个连接马上就真正地关闭了。在时间等待期间中,连接还处于一种中间过渡状态。这就可以使重复的FIN报文段(如果有的话)可以到达目的站因而可将其丢弃。这个计时器的值通常设置为一个报文段的寿命期待值的两倍
推荐阅读
- 热闹中的孤独
- 2018-02-06第三天|2018-02-06第三天 不能再了,反思到位就差改变
- 尽力
- 你到家了吗
- 这辈子我们都不要再联系了
- 死结。
- 我从来不做坏事
- 时间老了
- 喂,你结婚我给你随了个红包
- 赢在人生六项精进二阶Day3复盘