02-常见的面试题目-TCP

TCP是在IP网络层之上的传输层协议,用于提供port到port面向连接的可靠的字节流传输。

port到port:IP层只管数据包从一个IP到另一个IP的传输,IP层之上的TCP层加上端口后,就是面向进程了,每个port都可以对应到用户进程

1. TCP和UDP的区别和优缺点及应用场景

https://www.cnblogs.com/GuoXinxin/p/11657676.html

①TCP协议是有连接的,有连接的意思是开始传输实际数据之前TCP的客户端和服务器端必须通过三次握手建立连接,会话结束之后通过四次挥手结束连接。而UDP是无连接的
②TCP协议保证数据按序发送,按序到达,提供超时重传来保证可靠性,但是UDP不保证按序到达,甚至不保证到达,只是努力交付,即便是按序发送的序列,也不保证按序送到。
③TCP有流量控制和拥塞控制,而UDP没有,所以UDP即使网络拥堵客户端的发送速率也不会有影响
④TCP协议所需资源多,TCP首部需20个字节(不算可选项),UDP首部字段只需8个字节。
⑤TCP只支持一对一通信,而UDP支持一对一,一对多,多对多通信
⑥TCP是面向字节流,可靠的服务,,发送的是一个流数据。UDP是面向报文,不可靠的服务,一个一个的发,一个一个的收。
⑦TCP注重数据安全性,UDP数据传输快,因为不需要连接等待,少了许多操作,但是其安全性却一般

 

采用TCP传输协议的MSN比采用UDPQQ传输文件

但并不能说QQ的通信是不安全的,因为程序员可以手动对UDP的数据收发进行验证, 比如发送方对每个数据包进行编号然后由接收方进行验证什么的。

2. TCP三次握手及原因

为什么不能进行两次握手?

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁

3. 三次握手过程中有哪些不安全性

  1)伪装的IP向服务器发送一个SYN请求建立连接,然后服务器向该IP回复SYN和ACK,但是找不到该IP对应的主机,当超时时服务器收不到ACK会重复发送。当大量的攻击者请求建立连接时,服务器就会存在大量未完成三次握手的连接,服务器主机backlog被耗尽而不能响应其它连接。即SYN泛洪攻击 ,(属于DOS的一种,发送大量的半连接请求,耗费CPU和内存资源,引起网络堵塞甚至系统瘫痪)

当你服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。在Linux下可以如下命令检测是否被Syn攻击

netstat -n -p TCP | grep SYN_RECV

  防范措施: 
  1、降低SYN timeout时间,使得主机尽快释放半连接的占用 
  2、采用SYN cookie设置,如果短时间内连续收到某个IP的重复SYN请求,则认为受到了该IP的攻击,丢弃来自该IP的后续请求报文 
  3、在网关处设置过滤,拒绝将一个源IP地址不属于其来源子网的包进行更远的路由 
  2)当一个主机向服务器发送SYN请求连接,服务器回复ACK和SYN后,攻击者截获ACK和SYN。然后伪装成原始主机继续与服务器进行通信

4. TCP四次挥手及原因

5. 为什么TCP可以可靠传输

拥塞控制,流量窗口,慢启动,快重传,快恢复。。。。

6. TIME_WAIT状态持续时间及原因

  1. 为了可靠的断开TCP连接,假设最后客户端回复的ACK丢失,服务器端会在超时时间到来时,重传最后一个FIN包。ACK和FIN在网络中的最长生存时间就为2MSL,这样就可以可靠的断开TCP的双向连接。
  2. 一个数据包在网络中的最长生存时间为MSL,持续2MSL时间,可以让上一次连接的数据包在网络中消失,以防影响下一次连接。

所谓的2MSL是两倍的MSL(Maximum Segment Lifetime最大 报文段存活时间(往返时间))。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

7. 超时重传和快速重传 

  1. 超时重传:当超时时间到达时,发送方还未收到对端的ACK确认,就重传该数据包
  2. 快速重传:当后面的序号先到达,如接收方接收到了1、 3、 4,而2没有收到,就会立即向发送方重复发送三次ACK=2的确认请求重传。如果发送方连续收到3个相同序号的ACK,就重传该数据包。而不用等待超时 

8. TCP首部长度,有哪些字段(画出TCP报文)?及TCP选项有哪些?

最少20字节,因为TCP的头部中20字节的首部是固定的

 

TCP首部选项字段多达40B,一些常用的字段有: 
  1)选项结束字段(EOP,0x00),占1B,一个报文段仅用一次。放在末尾用于填充,用途是说明:首部已经没有更多的消息,应用数据在下一个32位字开始处 
  2)无操作字段(NOP, 0x01),占1B,也用于填充,放在选项的开头 
  3)MSS(最大报文段长度),格式如下:种类(1B,值为2),长度(1B,值为4),数值(2B) 
  用于在连接开始时确定MSS的大小,如果没有确定,就用默认的(一般实现是536B) 
  4)窗口扩大因子,格式如下:种类(1B,值为3),长度(1B,值为3),数值(1B) 
  新窗口值 = 首部窗口值 * 2的(扩大因子)次方 
  当通信双方认为首部的窗口值还不够大的时候,在连接开始时用这个来定义更大的窗口。仅在连接开始时有效。一经定义,通信过程中无法更改。 
  5)时间戳(应用测试RTT和防止序号绕回) 
  6)允许SACK和SACK选项 

9. TCP在listen时的参数backlog的意义

linux内核中会维护两个队列: 
  1)未完成队列:接收到一个SYN建立连接请求,处于SYN_RCVD状态 
  2)已完成队列:已完成TCP三次握手过程,处于ESTABLISHED状态 
  当有一个SYN到来请求建立连接时,就在未完成队列中新建一项。当三次握手过程完成后,就将套接口从未完成队列移动到已完成队列。 
  backlog被定义为两个队列的总和的最大值,也将backlog的1.5倍作为未完成队列的最大长度,一般将backlog指定为5 。 

10. accept发生在三次握手的哪一步

accept会监听已完成队列是否非空,当队列为空时,accept就会阻塞。当队列非空时,就从已完成队列中取出一项并返回。 
而已完成队列中的都是三次握手过程已经完成的,因此accept发生在三次握手之后

三次握手是发生在connect函数中,connect函数执行成功就相当于已经建立三次握手

11. 有哪些应用层协议是基于TCP的,哪些是基于UDP的

  • TCP: FTP、HTTP、Telnet、SMTP、POP3、HTTPS
  • UDP:DNS、SNMP、NFS

12. TCP报文长度是在TCP三次握手中哪一次确定的(第三次)

这个是关于TCP报文的最大报文段长度mss的相关问题。在TCP连接的前两次握手中(SYN报文中),通信双方都会在选项字段中告知对方自己期待收到最大报文长度(mss值),以双方两个SYN报文中最小的mss最为本次数据传输的mss值。通信双方以“协商”的方式来确定报文长度的,前两次握手是告诉对方自己的mss值,在第三次握手确定mss值

13. TCP报文长度是由什么确定的

这个跟具体传输网络有关,以太网的MTU为1500字节Internet的MTU为576字节

MTU是网络层的传输单元,那么MSS = MTU - 20字节(IP首部) - 20字节(TCP首部)。所以以太网的MSS为1460字节,而Internet的MSS为536字节

14. 如果TCP连接过程中,第三次握手失败怎么办

server端发送了SYN+ACK报文后就会启动一个定时器,等待client返回的ACK报文。如果第三次握手失败的话client给server返回了ACK报文,server并不能收到这个ACK报文。那么server端就会启动超时重传机制,超过规定时间后重新发送SYN+ACK,重传次数根据/proc/sys/net/ipv4/tcp_synack_retries来指定,默认是5次。如果重传指定次数到了后,仍然未收到ACK应答,那么一段时间后,server自动关闭这个连接但是client认为这个连接已经建立,如果client端向server写数据,server端将以RST包响应,方能感知到server的错误。

15. DOS攻击 拒绝服务攻击

DoS(分布式拒绝服务攻击) DOS攻击利用合理的服务请求占用过多的服务资源,使正常用户的请求无法得到响应

常见的DOS攻击有计算机网络带宽攻击和连通性攻击。

  1. 带宽攻击指以极大的通信量冲击网络,使得所有可用网络资源都被消耗殆尽,最后导致合法的用户请求无法通过。
  2. 连通性攻击指用大量的连接请求冲击计算机,使得所有可用的操作系统资源都被消耗殆尽,最终计算机无法再处理合法用户的请求。

16. 死亡值ping ???

许多操作系统的TCP/IP协议栈规定ICMP包大小为64KB(网间控制报文),且在对包的标题头进行读取之后,要根据该标题头里包含的信息来为有效载荷生成缓冲区。 ”死亡值ping”就是故意产生畸形的测试ping包,声称自己的尺寸超过ICMP上限,也就是加载的尺寸超过64KB上限,使未采取保护措施的网络系统出现内存分配错误,导致TCP/IP协议栈崩溃,最终接收方宕机。 

 

17. 画一下TCP的状态转移图

18. 如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。

服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

19. 为什么连接的时候是三次握手,关闭的时候却是四次握手

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

21. 通过TCP协议建立连接的两方,如果一方突然发生故障(比如断电)断开了连接,那么一下说法错误的是()?

  • A: TCP协议会自动检测连接是否断开,经过一段时间后另外一段会收到TCP连接断开的通知
  • B: 如果设置了TCP_KEEPALIVE,那么对端能够马上收到断开的信息
  • C: 可以自己实现心跳检测的方法来确定对方是不是已经断开连接
  • D: 另外一方能够马上知道连接已经断开

正确答案:A B D

TCP连接不能自动检查断连的现象; 所以A选项错误

TCP中KEEPALIVE机制是默认不打开的,需要通过setsockopt将SOL_SOCKET.SO_KEEPALIVE设置为1则是打开,打开后会定时向连接对方发送ACK包(linux下默认是7200s 即2小时发送一次握手信息),如果在发送ACK包后对方不回应才能检测道对方的断开信息,所以B错误;
Heartbeat机制是客户端每隔一段时间向服务器发送数据包,来通知服务端该客户端保持连接。所以C正确
综合AB,D是错误的

20. TCP中出现RST包的几种情况

在TCP协议中RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认

共有四种情况:

1 端口未打开

服务器程序端口未打开而客户端来连接。这种情况是最为常见和好理解的一种了。去telnet一个未打开的TCP的端口可能会出现这种错误。这个和操作系统的实现有关。在某些情况下,操作系统也会完全不理会这些发到未打开端口请求。

比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。这种情况很常见。特别是服务器程序core dump之后重启之前连续出现RST的情况会经常发生

当然在某些操作系统的主机上,未必是这样的表现。比如向一台WINDOWS7的主机发送一个连接不存在的端口的请求,这台主机就不会回应。

2 请求超时

曾经遇到过这样一个情况:一个客户端连接服务器,connect返回-1并且error=EINPROGRESS。 直接telnet发现网络连接没有问题。ping没有出现丢包。用抓包工具查看,客户端是在收到服务器发出的SYN之后就莫名其妙的发送了RST。

比如像下面这样:

有89、27两台主机。主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。但是主机27却很不友好,莫名其妙的发送了一个RST表示我不想连接你了。

后来经过排查发现,在主机89上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。而我们看上面的抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。(从15:01:27.799961到15:01:27.961886, 小数点之后的单位是微秒)。因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据

3 提前关闭

关于TCP,我想我们在教科书里都读到过一句话,'TCP是一种可靠的连接'。 而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?你猜对了,RST。

例子:

server:监听一个TCP端口然后当有客户端来连接的时候fork一个子进程来处理。每次只是读socket的前4096个字节,然后就关闭掉连接。

client:打开一个socket然后连接一个服务器并发送5000个字节。刚才我们看服务器的代码,每次只接收4096个字节。

那么就是说客户端发送的剩下的4个字节服务端的应用程序没有接收到,服务器端的socket就被关闭掉。

这种情况下会发生什么状况呢,还是抓包看一看。

前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。和我们的预期一致。

4 在一个已关闭的socket上收到数据

如果某个socket已经关闭,但依然收到数据也会产生RST。

客户端在服务端已经关闭掉socket之后,仍然在发送数据。这时服务端会产生RST。

21. 服务端几种情况下的操作:

如果客户端已经接受到一个RST数据报的时候,这个时候在向服务器端发送数据的时候,内核会向客户端进程发送一个SIGPIPE信号,是客户端进程结束

服务器主机崩溃的状态:

如果,客户端和服务器已经建立了连接的时候,此时服务器崩溃(达到这一标准可以把服务器的网线拔掉,这个时候,服务器就不能发送FIN数据报了,和关机不一样的)

此时如果客户端向服务器发送数据的时候,因为服务器已经不存在了,那么客户端就不能接受到服务器给客户端的ack信息,这个时候,客户端建立的是TCP连接,就会重发数据报,发送多少次之后就会返回超时,前面所说的ETIMEOUT

服务器主机崩溃后重启:

当客户端和服务器已经建立连接的时候,服务器发生崩溃,重新启动的时候,丢失了原来和客户端的连接信息,这个时候,当客户端向服务器发送数据的时候(客户端并不知道,服务器已经忘记三次握手了),此时服务器发送RST数据报,就结束了客户端的发送。

服务器关机:

会断开tcp连接,会发送FIN数据报

22. 从TCP协议的原理来谈谈rst复位攻击

TCP是在IP网络层之上的传输层协议,用于提供port到port面向连接的可靠的字节流传输。

port到port:IP层只管数据包从一个IP到另一个IP的传输,IP层之上的TCP层加上端口后,就是面向进程了,每个port都可以对应到用户进程。

1、为了能够说清楚下面的RST攻击,需要结合上图说说:SYN标志位、序号、滑动窗口大小。

建立连接的请求中,标志位SYN都要置为1,在这种请求中会告知MSS段大小,就是本机希望接收TCP包的最大大小。

发送的数据TCP包都有一个序号。它是这么得来的:最初发送SYN时,有一个初始序号,根据RFC的定义,各个操作系统的实现都是与系统时间相关的。之后,序号的值会不断的增加,比如原来的序号是100,如果这个TCP包的数据有10个字节,那么下次的TCP包序号会变成110

滑动窗口用于加速传输,比如发了一个seq=100的包,理应收到这个包的确认ack=101后再继续发下一个包,但有了滑动窗口,只要新包的seq与没有得到确认的最小seq之差小于滑动窗口大小,就可以继续发

2、滑动窗口

滑动窗口毫无疑问是用来加速数据传输的。TCP要保证“可靠”,就需要对一个数据包进行ack确认表示接收端收到。

  • 有了滑动窗口,接收端就可以等收到许多包后只发一个ack包,确认之前已经收到过的多个数据包
  • 有了滑动窗口,发送端在发送完一个数据包后不用等待它的ack,在滑动窗口大小内可以继续发送其他数据包

举个例子来看吧。

 

 标志位为.表示所有的flag都为0。标志位P表示flag为PSH的TCP包,用于快速传输数据。

前三个包是三次握手,客户端表示自己的滑动窗口大小是65535(我的XP机器),服务器端表示滑动窗口是5840(屏幕宽了,没截出来)。从第四个包开始,客户端向服务器发送PSH包,数据长度是520字节,服务器发了ack确认包。注意此时win窗口大小发生了改变哈。以此类推。

倒数第二、三包,服务器在滑动窗口内连续向客户端发包,客户端发送的ack 124同时确认了之前的两个包。这就是滑动窗口的功能了。

3、RST攻击

A和服务器B之间建立了TCP连接,此时C伪造了一个TCP包发给B,使B异常的断开了与A之间的TCP连接,就是RST攻击。

那么伪造什么样的TCP包可以达成目的呢?我们至顶向下的看。

假定C伪装成A发过去的包,这个包如果是RST包的话,毫无疑问,B将会丢弃与A的缓冲区上所有数据,强制关掉连接

如果发过去的包是SYN包,那么,B会表示A已经发疯了(与OS的实现有关),正常连接时又来建新连接,B主动向A发个RST包,并在自己这端强制关掉连接

这两种方式都能够达到复位攻击的效果。似乎挺恐怖,然而关键是,如何能伪造成A发给B的包呢?这里有两个关键因素,源端口和序列号

一个TCP连接都是四元组,由源IP、源端口、目标IP、目标端口唯一确定一个连接。所以,如果C要伪造A发给B的包,要在上面提到的IP头和TCP头,把源IP、源端口、目标IP、目标端口都填对。这里B作为服务器,IP和端口是公开的,A是我们要下手的目标,IP当然知道,但A的源端口就不清楚了,因为这可能是A随机生成的。当然,如果能够对常见的OS如windows和linux找出生成source port规律的话,还是可以搞定的。

序列号问题是与滑动窗口对应的,伪造的TCP包里需要填序列号如果序列号的值不在A之前向B发送时B的滑动窗口内,B是会主动丢弃的。所以我们要找到能落到当时的AB间滑动窗口的序列号。这个可以暴力解决,因为一个sequence长度是32位,取值范围0-4294967296,如果窗口大小像上图中我抓到的windows下的65535的话,只需要相除,就知道最多只需要发65537(4294967296/65535=65537)个包就能有一个序列号落到滑动窗口内。RST包是很小的,IP头+TCP头也才40字节,算算我们的带宽就知道这实在只需要几秒钟就能搞定。

那么,序列号不是问题,源端口会麻烦点,如果各个操作系统不能完全随机的生成源端口,或者黑客们能通过其他方式获取到source port,RST攻击易如反掌,后果很严重。

23. OSI与TCP/IP各层的结构和功能,协议和作用

OSI七层模型对应TCP/IP四层模型,只是分法不同而已。
     应用层:提供应用层服务,文件传输(FTP),电子邮件(SMTP),  主要的协议还有HTTP(超文本传输协议),DNS,和telnet
     表示层:用于数据格式化,代码转换,数据加密,没有协议
     会话层:解除或建立与别的接点的联系,没有协议
     传输层:TCP UDP
     网络层: IP  ICMP(ping主要实现), OSPF(全局泛洪,主要用于IP选路) 
     数据链路层   ARP(地址解析协议,根据IP地址获得MAC地址)
     物理层:

 

 按照TCP/IP分的话,就四层:应用层,传输层,网络层还有不知道叫什么名字,主机到网络层?(包含物理层和数据链路层)

 

 

宿舍用的是路由器还是交换机?

 

22. TCP拥塞控制

拥塞控制就是防止过多的数据注入到网络中,这样使得网络中的路由器或者链路不至于过载。TCP拥塞控制方法主要包括:慢开始,拥塞避免,快重传和快恢复
慢开始是指发送方先设置cwnd=1,一次发送一个报文段,随后每经过一个传输轮次,拥塞串口cwnd就加倍,其实增长并不慢,以指数形式增长。还要设定一个慢开始门限,当cwnd>门限值,改用拥塞避免算法。拥塞避免算法使cwnd按线性规律缓慢增长。当网络发生延时门限值减半,拥塞窗口执行慢开始算法

之后又提出了快重传和快恢复,见下一题

23. TCP快速重传与快速恢复原理

 

24. 滑动窗口协议

 

25. 回退n针协议

 

26. 选择重传协议

 

27. 超时重传

 

 

28. tcp/ip 端口范围

 

29. TCP/IP中MSL详解及MSL 字段类型范围大小字节大小

 

30. MSL、TTL和RTT

 

 

28. 以太网与Internet的区别

 

29. 找UDP编程的项目

 

 

 

 

 

以上收集于:

http://www.pianshen.com/article/3633335616/

https://msd.misuland.com/pd/3094725972029606300

https://blog.csdn.net/wendy_keeping/article/details/76098504

https://www.cnblogs.com/huajiezh/p/7492416.html

https://www.cnblogs.com/zhwcs/p/10440013.html

 https://www.iteye.com/blog/russelltao-1405349

posted @ 2019-10-14 11:23  GuoXinxin  阅读(586)  评论(0编辑  收藏  举报