Posix API与网络协议栈的实现原理

简介: Posix API与网络协议栈的实现原理


面试中协议栈常问的点

1. TCP三次握手过程?

2. TCP四次挥手过程?

3. 为什么建立连接需要三次握手,而断开 连接需要四次握手?

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

5.大量的time_wait于close_wait

6. 超时重传和快速重传

7. TCP首部长度,有哪些字段

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

9. Accept发生在三次握手的哪一步?

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

11.TCP与UDP的区别

udp主要用在哪里:

1.大量数据传输,(比如迅雷vip,大量下载的时候其他人会很卡,因为udp没有拥塞控制)

2.实时性。

3.dns协议。(浏览器打开www.baidu.com获取ip地址的过程采用的是udp。

udp的缺点有哪些:

1.不稳定                          

建立连接的过程:

udp不建立连接,没有三次握手,也可以调用connect()函数,udp的这个connect()函数没有发送具体的数据,仅此尝试一下这条链路是不是通的,对方的这个ip地址和端口号有没有存在。如果返回是个正数成功的话,那么接下来调用sendto()成功的概率要比不调用connect()高很多。

tcp在发送数据之前是要调用connect()函数建立连接的,服务器必须要处在listen()的状态才能接收连接。

我们所调用的这些API都是在应用程序里面调用的。三次握手(四次挥手)的过程是发生在TCP/IP协议栈和协议栈之间。这是协议栈帮忙实现的,跟我们的应用程序没有关系。

send()这个函数干的事情就是将数据从用户空间copy到协议栈TCB里面,一个fd对应一个TCB,通过fd,找到对应的TCB。再次调用send()也只是继续copy到协议栈里面的send_buffer里面。 至于这个数据怎么到对方的协议栈里面的,不是应用程序管的,是tcp协议栈自己去做的,就是需要tcp的确认机制,慢启动,拥塞控制...等。

                                 commit_skb()

调用connect()函数的时候,此时应用程序会把本机的ip和port。copy到协议栈里面,协议栈会自己准备一个包(SYN)(TCP头八个状态位里面把SYN状态位置1),然后把这个数据发给对端。服务端会返回一个ACK 和一个SYN。并且保存服务端的一些信息(因为服务端只有一个,客户端可以有n多个) ,当第三次握手来了之后,服务端会拿着这个信息和去半连接队列里面对比有没有这个节点,然后再把这个节点拿到全连接队列里面来(这个节点不是拷贝,是移动)。(进入全连接队列的前提条件是第三次握手过来,并且在半连接队列里面有,这两个条件同时满足,才进入全连接队列)。accept()这个函数只干两件事情,1. 从accept队列里面拿出一个节点,2. 位这个节点分配一个与之对应的fd,然后返回这个fd。(如果此时这个全连接队列里面没有节点,accept会进入条件等待,等待全连接队列里面有节点,此时会进入阻塞状态)。如果此时这个fd被设置为非阻塞fcntl(fd,noblock),此时accept就会立即返回-1。

第三次握手的时候通过什么找到半连接队列里面的对应的节点?  

通过五元组(sip , dip , sport , dport ,porto),这些信息在tcp/ip协议头和ip协议头里面都有。目的ip和目的端口都是一样的,只需要拿sip和sport对比一下就知道了。

半连接队列里面的节点也叫做TCP控制块(TCB)

半连接队列节点的生命周期它有多长?

tcp的(11个状态)状态是存在半连接队列的节点里面的,伴随着连接过程的整个生命周期。

脏数据:  多个客户端同时sendto给一个fd的时候,recvfrom的数据可能会乱序。 一个fd对应一个recvbuffer。   在这个recvbuffer里面无法区分数据是哪个客户端来的。

怎么解决udp并发的问题:                       模拟tcp

1. recvfrom(&addr) 接收到第一帧的信息,拿到他的ip地址和端口号。

2. 新建一个fd,调用sendto(fd ,...) 给对端发。 出现了一个fd对应一个客户端的现象。

如果接收到第一帧包不对的话就返回,然后超时重发。

TCP是如何保证顺序的

TCP的超时重传机制,每发送一个包,会启动一个200ms的定时器。比如当检测到3号包没到的话,将重新发送3号以及后面的所有包。(这也是tcp缺点之一: 确认时间周期长,重传的时候会重传那些即使已经收到的包---重发的次数有点多) ack就是一个数字,可以理解为是多少号包以前的全部收到了。      tcp会延迟发送ack

TCP的超时重传只会在发送方启动一个定时器,对方是不会启动定时器的,如果对方回的这个ACK丢失了,那么也会引起发送方的超时重传。

tcp一开始是慢启动的,最先是指数级增长,到一定程度后线性增长,当线性增长到达最大值之后砍一半,继续线性增长,后面这个过程叫拥塞控制(发包的数量)。

断开连接

调用close、shutdown 、connect、send这四个函数的时候会有一个数据发送的过程

当对端close的时候,epoll里面就会触发EPOLLRDHUP。如果两端都close了,自己也发送出去了FIN并且也收到了ACK,那么此时如果这个fd还在EPOLL里面。那么这一步就会触发EPOLLHUP

大量的time_wait怎么办?

首先是主动调用close(),主动方才有time_wait。如果作为服务方,出现大量的time_wait是不正常的现象(你的服务器代码里面出现了主动调用close的现象)。(先检查你的逻辑看看调用close的地方是不是正常的,如果不是正常的就把业务代码改一下。如果是正常的,可以通过setsockopt(REUSE),设置为重用。当这个TCB设置为重用之后,这个TCP不会被释放,会再次拿来使用。能够在一定限度上去减少time_wait。

time_wait的作用:

保证最后一个fin接收,对端能够收到最后一个ack,当对端发送最后一个fin的时候对端会启动一个定时器,如果ack没有及时收到,fin会进行重发,time_wait的作用就是当有fin过来的时候给对端回ack , 仅此一个作用。

如果没有time_wait:就会丢失最后一个ack,time_wait直接结束了,对应的tcb控制块被释放掉了,对方再发fin过来的时候没有tcb做响应,回不了数据,就会出现对端一直处于last_ack状态一直不会结束。

大量的close_wait怎么办?

当recv返回0,可以判断对端关闭了。此时进入close_wait状态。这时候出现大量的close_wait状态是因为服务端调用close这个过程延迟了。(服务端知道客户端断开连接了,但是在服务端调用close之前可能需要对客户端释放一些信息,还需要向客户端发送一些数据,这个逻辑代码可能有点长,延迟了close的调用)。(还有一些特殊情况就是你在服务端没有调用close)

这种时候就要看看你recv返回0之后你调用close是不是正确的时机。当recv返回0之后应该是立即调用close。然后把业务代码的解析和释放可以抛给另外一个线程,把这个fd(客户端)的信息抛给另外一个线程去释放业务代码。不应该在recv返回0这个流程里面处理。可以做成异步处理。

fin_wait_2状态能不能终止?   (大量fin_wait_2怎么解)

比如现在进入了fin_wait_2状态,等待着对方调用close,但是对方迟迟不调用close。所以此时出现了很多的这种close_wait 和 fin_wait_2。 (答案是没有) 。 当客户端调用完close之后,客户端能做的事情已经做完了,此时需要等待对方调用close。在逻辑代码上面已经没办法处理了。真的要强行禁止,只能kill。  

但是站在客户端的层次,一个连接出现一个fin_wait_2影响不大,再建立一个连接(connect)发送数据这也是OK的。但是这样周而复始就会出现大量的fin_wait_2的状态,当太多的时候只能kill掉或者通知对方处理,否则无解

同时close

当应用层发出关闭命令时,两端均从ESTABLISHED变为FIN _ WAIT_1。

这将导致双方各发送一个 FIN,两个FI N经过网络传送后分别到达另一端。收到FIN后,状态由F I N_WAIT_1变迁到 C L O S I N G,并发送最后的ACK。当收到最后的 ACK时,状态变化为TIME _ WAIT。

网路协议栈

Send缓冲区

send/recv

Udp数据帧

UDP协议

ARP协议

ICMP协议

总结:

服务端:

socket() : 文件系统分配一个fd , 并且给他分配一个TCB。

bind() :为TCB绑定一个本地ip地址和端口号。

listend() :把这个TCB置为一个Listen状态

accept() :为全连接队列里面取出一个节点。并为他分配一个fd

recv () : 从TCB的recvBuffer里面把数据拷贝出来。

send() :把数据copy到fd对应的sendBuffer里面。

close() : 1   准备一个fin包放到sendBuffer里面去,  2 回收fd

剩下的就跟应用程序没关系了。由协议栈决定。

客户端:

connect() : 准备一个SYN包交给协议栈发出去,等待三次握手完成之后再返回。

连接不成功会置错误值。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
4月前
|
JSON 监控 网络协议
干货分享“对接的 API 总是不稳定,网络分层模型” 看电商 API 故障的本质
本文从 OSI 七层网络模型出发,深入剖析电商 API 不稳定的根本原因,涵盖物理层到应用层的典型故障与解决方案,结合阿里、京东等大厂架构,详解如何构建高稳定性的电商 API 通信体系。
|
1月前
|
缓存 人工智能 API
API接口调用中的网络异常及解决方案
淘宝API是淘宝开放平台提供的接口集合,支持商品、交易、用户、营销等数据交互。开发者需注册获取App Key,通过签名认证调用API,结合沙箱测试、OAuth授权与安全策略,实现订单管理、数据监控等应用,提升电商自动化与数据分析能力。
|
9月前
|
网络协议 安全 网络安全
应用程序中的网络协议:原理、应用与挑战
网络协议是应用程序实现流畅运行和安全通信的基石。了解不同协议的特点和应用场景,以及它们面临的挑战和应对策略,对于开发者和用户都具有重要意义。在未来,随着技术的不断发展,网络协议也将不断优化和创新,为数字世界的发展提供更强大的支持。
275 1
|
12月前
|
网络协议
网络通信的基石:TCP/IP协议栈的层次结构解析
在现代网络通信中,TCP/IP协议栈是构建互联网的基础。它定义了数据如何在网络中传输,以及如何确保数据的完整性和可靠性。本文将深入探讨TCP/IP协议栈的层次结构,揭示每一层的功能和重要性。
669 5
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
226 13
|
12月前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
1456 2
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
网络协议 网络架构 数据格式
TCP/IP基础:工作原理、协议栈与网络层
TCP/IP(传输控制协议/互联网协议)是互联网通信的基础协议,支持数据传输和网络连接。本文详细阐述了其工作原理、协议栈构成及网络层功能。TCP/IP采用客户端/服务器模型,通过四个层次——应用层、传输层、网络层和数据链路层,确保数据可靠传输。网络层负责IP寻址、路由选择、分片重组及数据包传输,是TCP/IP的核心部分。理解TCP/IP有助于深入掌握互联网底层机制。
1547 2
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。