android tcp 面试

参考:https://www.cnblogs.com/wulala1119/p/4749892.html

tpc/ip 的四层模型

  • 网络接入层:将需要相互连接的节点接入网络中,从而为数据传输提供条件。
  • 网络互联层:找到要传输数据的目标节点。(IP协议)
  • 传输层:实际传输数据。(TCP 、UDP协议)
  • 应用层:使用接收到的数据。(HTTP、HTTPS、DNS协议)

tcp/ip 协议

是两个不同的协议,所起的作用也不一样。IP协议是用来查找地址的,对应着网际互联层,TCP协议是用来规范传输规则的,对应着传输层。IP只负责找到地址,具体传输工作交给TCP来完成。

TCP在传输之前会进行三次沟通,一般称为“三次握手”,传完数据断开的时候,要进行四次沟通,一般称为“四次挥手”。要理解这个过程首先需要理解TCP中的两个序号和三个标志位的含义:

  • seq:sequence number的缩写,表示所传数据的序号。TCP传输时每一个字节都有一个序号,发送数据时会将数据的第一个序号发送给对方,接收方会按序号检查是否接收完整了,如果没有接收完整就需要重新传送,这样就可以保证数据的完整性。
  • ack:asknoledgement number的缩写,表示确认号。接收端用它来给发送端反馈已经成功接收到的数据信息,它的值为希望接收的下一个数据包起始序号,也就是ack值所代表的序号前面数据已经成功接收到了。
  • ACK:确认位,只有ACK=1的时候ack才起作用。正常通信时ACK为1,第一次发起请求时因为没有需要确认接收的数据所以ACK为0。
  • SYN:同步位,用于在建立连接时同时序号。刚开始建立连接时并没有历史接收数据,所以ack也就没办法设置,这时按照正常的就无法运行了,SYN的作用就是来解决这个问题的,当接收端接收到SYN=1的报文时就会直接将ack设置为接收到的seq+1的值,注意这里面的值并不是校验后设置的,而是根据SYN直接设置的,这样正常的机制就可以运行了,所以SYN叫同步位。需要注意的是,SYN会在前面再次握手时都为1,这是因为通信的双方的ack都需要设置一个初始值。
  • FIN:终止位,用来在数据传输完毕后释放连接。
    android tcp 面试_第1张图片
    android tcp 面试_第2张图片

面试题

发送序号和确认序号问题

  • 例: TCP建立连接的过程采用三次握手,已知第三次握手报文的发送序列号为1000,确认序列号为2000,请问第二次握手报文的发送序列号和确认序列号分别为?
  • 答:看答案时请参考上面TCP连接建立的图。
  • 客户端:发送X
  • 服务端:发送Y, 确认X+1
  • 客户端:发送X+1(1000),确认Y+1(2000)
  • 可以反推第二次为1999,确认1000

SYN Flood 攻击原理及防御

SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。

原理
问题出在TCP连接的三次握手中,恶意的攻击者大量发送SYN报文,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。实际上如果服务器的TCP/IP栈不够强大,最后的结果往往是堆栈溢出崩溃—即使服务器端的系统足够强大,服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求(毕竟客户端的正常请求比率非常之小),此时从正常客户的角度看来,服务器失去响应,这种情况我们称作:服务器端受到了SYN Flood攻击(SYN洪水攻击)。

为什么TCP建立连接要三次握手

  • 首先得回答三次握手的目的是同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。
  • 然后可以回答为什么两次握手不行,两次握手可能因为丢包而出现死锁,假设在两次握手场景中,C向S发送请求,S收到并发送确认请求给C,这时候S认为连接已经建立,并开始发送数据给C,但是那个确认请求丢包了,C不认为请求建立了,C当然会拒绝接受S发送来的数据,并且再去请求连接。这样,一个资源就死锁了。

设置TIME_WAIT的原因

  • 可靠地实现TCP全双工连接的终止
  • TCP协议在关闭连接的四次握手过程中,最终的ACK是由主动关闭连接的一端(后面统称A端)发出的,如果这个ACK丢失,对方(后面统称B端)将重发出最终的FIN,因此A端必须维护状态信息(TIME_WAIT)允许它重发最终的ACK。如果A端不维持TIME_WAIT状态,而是处于CLOSED 状态,那么A端将响应RST分节,B端收到后将此分节解释成一个错误(在java中会抛出connection reset的SocketException)。
    因而,要实现TCP全双工连接的正常终止,必须处理终止过程中四个分节任何一个分节的丢失情况,主动关闭连接的A端必须维持TIME_WAIT状态
  • 允许老的重复分节在网络中消逝
  • TCP分节可能由于路由器异常而“迷途“,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个迟到的迷途分节到达时可能会引起问题。在关闭“前一个连接”之后,马上又重新建立起一个相同的IP和端口之间的“新连接”,“前一个连接”的迷途重复分组在“前一个连接”终止后到达,而被“新连接”收到了。为了避免这个情况,TCP协议不允许处于TIME_WAIT状态的连接启动一个新的可用连接,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个新TCP连接的时候,来自旧连接重复分组已经在网络中消逝。

大量 TIME_WAIT 产生的原因及解决办法

原因:对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态。

解决办法:

  • 开启socket重用,允许将TIME_WAIT的socket重新用于TCP连接
  • 开启快速回收。

大量CLOSE_WAIT产生的原因及解决办法

原因:对方关闭连接之后服务器程序自己没有进一步发出ack信号。换句话说,就是在对方连接 关闭之后,程序里 没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。

  • 解决办法:
    具体问题具体解决,总结一句话就是在处理资源时一定要记住自己申请的资源要记得主动释放。

参考:https://blog.csdn.net/shootyou/article/details/6622226

为什么TCP断开连接要四次挥手

因为tcp是全双工模式,接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据。

参考:https://blog.csdn.net/xifeijian/article/details/12777187

你可能感兴趣的:(android,学习,面试)