热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

网络知识梳理(后台开发人员面试必备)

最近在处理一个TCP粘包问题,虽然相关的知识都略知一二,但是好像让我完整的说出来细节,却还要查下资料,因此,整理列出来,以便复习。而且这些知识点是后台开发人员的必备基本功,相当于内

最近在处理一个TCP粘包问题,虽然相关的知识都略知一二,但是好像让我完整的说出来细节,却还要查下资料,因此,整理列出来,以便复习。而且这些知识点是后台开发人员的必备基本功,相当于内功,还是要多拿出来温故而知新。

1.不同协议层的限制值:

1.1 链路层(以太网)

局域网(无线是另一种协议)采用CSMA/CD协议,核心概念就是

通道共用,发送前监听冲突,冲突后重发

标准以太网帧长度下限:64byte

原理大概就是因为发送前要监听是否有其他人在使用通道,而根据通讯原理,64byte传输的时间就是知道是否有冲突的最小时间。

标准以太网帧长度上限:1518byte

这个值也是协议标准协会“拍脑袋”的结果。

一方面,如果太小,每次传输的利用率就低(TCP头部20byte,IP头部20byte,链路层头部18byte);另一方面,如果太大,就会导致共享通道被某一方霸占太久,而且,包太大,出错率高,缓存成本也要提高。

1.2 网络层

MTU: 1500byte(TCP标准化采用576byte)

因为“标准以太网帧长度上限”为1518byte,所以减去链路层18byte的头部,IP数据报的最大限制值就等于1500byte。

IP分片

注意和传输层的“数据报分段”区分。

如果IP数据报长度大于MTU,就需要分成几段传输,然后重组,分片和重组都是在网络层协议完成的。

因为TCP传输层才有提供超时和重传机制,网络层没有,所以如果有一片IP分片丢失,需要重传(TCP的重传),丢失的IP分片所属的TCP数据的所有IP分片,都要再重新传输。

1.3 传输层(TCP)

MSS

每个TCP数据报(去掉IP头部和TCP头部)的最长长度。如果未设置,默认为536byte(对应MTU576byte),一般在以太网,都是1460byte(1500-20-20)。

在TCP握手的前两次商议MSS值。

TCP分段

请区分 “TCP分段” 和 “IP分片”,两个是在不同协议层的概念。

如果TCP数据长度超过MSS,就要分段,然后重组。

因为MSS

2. Nagle 算法

Nagle算法

为了解决telnet场景下,敲一下键盘就发送一个字符,传输效率低导致网络阻塞的问题。

Nagle算法基本定义是:任意时刻,最多只能有一个未被确认的小段。 所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。

可以设置TCP_NODELAY来关闭,提高传输效率,缺点是实时交互性差。

TCP确认延迟机制

可以看出,Nagle算法受限于接收方发回ACK的时间间隔,因此与之配套的接收方使用“TCP确认延迟机制”。延迟默认为40ms,视情况调整数值。可以设置TCP_QUICKACK标志来关闭。

3. TCP粘包

为什么会出现TCP粘包?

在Nagle算法的作用下,假设在等待ACK期间,发送一段文字“hello”,然后又发送了“world”,假设MSS为7,这时对方接收到的就是“hellowo”。消息黏在一起,所以称为“粘包”。

解决方法:一般是使用标识来识别界限。加字段size来指明一个包的长度,或者是在一条数据的结尾加特殊的结束符(比如/n)。

为什么UDP不会粘包?

首先,在发送方,UDP没有Nagle算法来合并发送几个数据。

然后接收方,UDP是基于消息保护边界,不同于TCP的基于流传输。也就是UDP会使用链式保持每条接收的完整消息。比如发送方发了3条消息,UDP接收方会在缓存独立保存3条消息,而TCP则可能只接收到一条合并的消息;UDP需要recv 3次才能接收3条消息,TCP则可能recv一次就行了。

为什么UDP会采用链式保存接收到的消息?因为TCP是一对一的连接,而UDP是可能一对多的连接,为了区分不同发送方发来的消息,所以需要分开存放。

4. 为什么UDP没有发送缓冲区

首先需要大概了解一下TCP和UDP在执行write的原理

TCP在write的时候,系统把消息从用户态拷贝到内核的socket发送缓冲区,然后直接返回成功,接下来会有一系列操作会用到缓冲区(丢失重传,Nagle算法的合并,滑动窗口等等)。直到收到对方的ACK,内核才会把消息从发送缓冲区删除。

UDP在write的时候,因为是不可靠传输,所以只是把数据从用户态拷贝到内核,然后立即发送出去,不管对方是否能收到,所以不需要缓冲区。

TCP和UDP都有接收缓冲区

内核态和用户态的切换工作模式,决定了缓冲区的必要性。当然两种缓冲区的工作模式不一样。

TCP如果缓冲区满了,会通过滑动窗口的流量控制告诉对方不要再发了,不然会丢掉新包。UDP则只是简单的丢掉。

从缓冲区理解socket的阻塞和非阻塞操作

从上面可以看到,不管是read或者write,操作其实都是消息在用户态和内核态的拷贝。因此,阻塞其实就是看内核缓冲区有没有数据。

比如阻塞模式下,read会一直等待内核缓冲区有数据才返回,而非阻塞模式,则会立即返回;阻塞模式下,write会一直等待内核有足够空间写入数据才返回,而非阻塞模式,有空间则写入,没有就会告诉你失败。

5. 三次握手和四次挥手

《网络知识梳理(后台开发人员面试必备)》

为什么需要3次握手

因为是建立一个全双工的连接,所以互相都要得到对方的确认,以及通信的双方要互相通知对方自己的初始化的Sequence Number,所以流程顺序应该是这样的:(1.A跟B说我要连接;2.B答应并且返回x+1;3.B跟A说要建立连接;4.A答应并且返回y+1。)

总共有4个步骤,但是因为步骤2和3可以合并一起,所以就成了“3次握手”。

注意:SeqNum的增加是和传输的字节数相关的,握手和挥手都是1个字节,所以才加一。

如果A在执行步骤4之前就断开了,B会重发步骤3。在Linux下,默认重试次数为5次,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s才知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才会把断开这个连接。

SYN flood攻击

给服务器发了一个SYN后,就下线了,于是服务器需要默认等63s才会断开连接,这样,攻击者就可以把服务器的syn连接的队列耗尽,让正常的连接请求不能处理。

于是,Linux下给了一个叫tcp_synCOOKIEs的参数来应对这个事——当SYN队列满了后,TCP会通过源地址端口、目标地址端口和时间戳打造出一个特别的Sequence Number发回去(又叫COOKIE),如果是攻击者则不会有响应,如果是正常连接,则会把这个 SYN COOKIE发回来,然后服务端可以通过COOKIE建连接(即使你不在SYN队列中)。请注意,请先千万别用tcp_synCOOKIEs来处理正常的大负载的连接的情况。因为,syncCOOKIEs是妥协版的TCP协议,并不严谨。

对于正常的请求,你应该调整三个TCP参数可供你选择,第一个是:tcp_synack_retries 可以用他来减少重试次数;第二个是:tcp_max_syn_backlog,可以增大SYN连接数;第三个是:tcp_abort_on_overflow 处理不过来干脆就直接拒绝连接了。

5. TCP滑动窗口

TCP滑动窗口是网络流控的一种实现方法。接收方通过通知发送方自己的窗口大小,从而控制发送方的发送速度,达到防止发送方发送速度过快而导致自己被淹没的目的。

《网络知识梳理(后台开发人员面试必备)》
《网络知识梳理(后台开发人员面试必备)》

由上图可以看出窗口的动态变化过程:

1.一开始窗口大小360,Client发送140长度的数据给Server,Server接收返回ACK并调整窗口为260;

2.Client接收到ACK并调整窗口为260,然后发送180的数据给Server,Server接收后返回ACK又调整窗口为80;

3.Client接收到ACK并调整窗口为80,然后发送80的数据给Server,Server接收后返回ACK调整窗口为0;

TCP是双工的协议,会话的双方都可以同时接收、发送数据。TCP会话的双方都各自维护一个“发送窗口”和一个“接收窗口”

其中各自的“接收窗口”大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。

各自的“发送窗口”则要求取决于对端通告的“接收窗口”,要求相同

好了,差不多就这些了,好像还有非常多没有涉及,不过相信把这些都理解好了,已经足够应付大多数的面试了。

以后有时间再整理一个应用层协议方面的文章。


推荐阅读
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了如何找到并终止在8080端口上运行的进程的方法,通过使用终端命令lsof -i :8080可以获取在该端口上运行的所有进程的输出,并使用kill命令终止指定进程的运行。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
author-avatar
手机用户2602914627
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有