首页 » Web前端 » phpsocketrecvmsg技巧_深入理解TCPIP的底层队列实现事理

phpsocketrecvmsg技巧_深入理解TCPIP的底层队列实现事理

访客 2024-12-04 0

扫一扫用手机浏览

文章目录 [+]

自早年次学习了TCP/IP的拥塞掌握算法后,我加倍想要更加深入的理解TCP/IP的一些底层事理,搜索了很多网络上的资料,看到了陶辉大神关于高性能网络编程的专栏,收益颇多。
本日就总结一下,并且加上自己的一些思考。

 我自己比较理解Java措辞,对Java网络编程的理解就止于Netty框架的利用。
Netty的源码贡献者Norman Maurer对付Netty网络开拓有过一句建议,\公众Never block the event loop, reduce context-swtiching\"大众。
也便是只管即便不要壅塞IO线程,也只管即便减少线程切换。

phpsocketrecvmsg技巧_深入理解TCPIP的底层队列实现事理

 为什么不能壅塞读取网络信息的IO线程呢?这里就要从经典的网络C10K开始理解,做事器如何支持并发1万要求。
C10K的根源在于网络的IO模型。
Linux 中网络处理都用同步壅塞的办法,也便是每个要求都分配一个进程或者线程,那么要支持1万并发,难道就要利用1万个线程处理要求嘛?这1万个线程的调度、高下文切换乃至它们占用的内存,都会成为瓶颈。
办理C10K的通用办法便是利用I/O 多路复用,Netty便是这样。

phpsocketrecvmsg技巧_深入理解TCPIP的底层队列实现事理
(图片来自网络侵删)

 Netty有卖力做事端监听建立连接的线程组(mainReactor)和卖力连接读写操作的IO线程组(subReactor),还可以有专门处理业务逻辑的Worker线程组(ThreadPool)。

三者相互独立,这样有很多好处。
一是有专门的线程组卖力监听和处理网络连接的建立,可以防止TCP/IP的半连接行列步队(sync)和全连接行列步队(acceptable)被占满。
二是IO线程组和Worker线程分开,双方并行处理网络I/O和业务逻辑,可以避免IO线程被壅塞,防止TCP/IP的吸收报文的行列步队被占满。
当然,如果业务逻辑较少,也便是IO 密集型的轻打算业务,可以将业务逻辑放在IO线程中处理,避免线程切换,这也便是Norman Maurer话的后半部分。

 TCP/IP怎么就这么多行列步队啊?本日我们就来细看一下TCP/IP的几个行列步队,包括建立连接时的半连接行列步队(sync),全连接行列步队(accept)和吸收报文时的receive、outoforder、prequeue以及backlog行列步队。

建立连接时的行列步队

 如上图所示,这里有两个行列步队:syns queue(半连接行列步队)和accept queue(全连接行列步队)。
三次握手中,做事端吸收到客户真个SYN报文后,把干系信息放到半连接行列步队中,同时回答SYN+ACK给客户端。

 第三步的时候做事端收到客户真个ACK,如果这时全连接行列步队没满,那么从半连接行列步队拿出干系信息放入到全连接行列步队中,否则按 tcp_abort_on_overflow的值来实行干系操作,直接抛弃或者过一段韶光在重试。

吸收报文时的行列步队

 比较于建立连接,TCP在吸收报文时的处理逻辑更为繁芜,干系的行列步队和涉及的配置参数更多。

 运用程序吸收TCP报文和程序所在做事器系统吸收网络里发来的TCP报文是两个独立流程。
二者都会操控socket实例,但是会通过锁竞争来决定某一时候由谁来操控,由此产生很多不同的场景。
例如,运用程序正在吸收报文时,操作系统通过网卡又吸收到报文,这时该如何处理?若运用程序没有调用read或者recv读取报文时,操作系统收到报文又会如何处理?

 我们接下来就以三张图为主,先容TCP吸收报文时的三种场景,并在个中先容四个吸收干系的行列步队。

吸收报文场景一

上图是TCP吸收报文场景一的示意图。
操作系统首先吸收报文,存储到socket的receive行列步队,然后用户进程再调用recv进行读取。

1) 当网卡吸收报文并且判断为TCP协议时,经由层层调用,终极会调用到内核的 tcp_v4_rcv方法。
由于当前TCP要吸收的下一个报文正是S1,以是 tcp_v4_rcv函数将其直接加入到 receive行列步队中。
receive行列步队是将已经吸收到的TCP报文,去除了TCP头部、排好序放入的、用户进程可以直接按序读取的行列步队。
由于socket不在用户进程高下文中(也便是没有用户进程在读socket),并且我们须要S1序号的报文,而恰好收到了S1报文,因此,它进入了 receive行列步队。

2) 吸收到S3报文,由于TCP要吸收的下一个报文序号是S2,以是加入到 out_of_order行列步队,所有乱序的报文会放在这里。

3) 接着,收到了TCP期望的S2报文,直接进入 recevie行列步队。
由于此时 out_of_order行列步队不为空,须要检讨一下。

4) 每次向 receive行列步队插入报文时都会检讨 out_of_order行列步队,由于吸收到S2报文后,期望的的序号为S3,以是 out_of_order行列步队中的S3报文会被移到 receive行列步队。

5) 用户进程开始读取socket,先在进程等分配一块内存,然后调用 read或者 recv方法。
socket有一系列的具有默认值的配置属性,比如socket默认是壅塞式的,它的 SO_RCVLOWAT属性值默认为1。
当然,recv这样的方法还会吸收一个flag参数,它可以设置为 MSG_WAITALL、 MSG_PEEK、 MSG_TRUNK等等,这里我们假定为最常用的0。
进程调用了 recv方法。

6) 调用 tcp_recvmsg方法

7) tcp_recvmsg方法会首先锁住socket。
socket是可以被多线程利用的,而且操作系统也会利用,以是必须处理并发问题。
要操控socket,就先获取锁。

8) 此时, receive行列步队已经有3个报文了,将第一个报文拷贝到用户态内存中,由于第五步中socket的参数并没有带 MSG_PEEK,以是将第一个报文从行列步队中移除,从内核态开释掉。
反之, MSG_PEEK标志位会导致 receive行列步队不会删除报文。
以是, MSG_PEEK紧张用于多进程读取同一套接字的环境。

9) 拷贝第二个报文,当然,实行拷贝前都会检讨用户态内存的剩余空间是否足以放下当前这个报文,不足时会直接返回已经拷贝的字节数。

10) 拷贝第三个报文。

11) receive行列步队已经为空,此时会检讨 SO_RCVLOWAT这个最小阈值。
如果已经拷贝字节数小于它,进程会休眠,等待更多报文。
默认的 SO_RCVLOWAT值为1,也便是读取到报文就可以返回。

12) 检讨 backlog行列步队, backlog行列步队是用户进程正在拷贝数据时,网卡收到的报文会进这个行列步队。
如果此时 backlog行列步队有数据,就顺带处理下。
backlog行列步队是没有数据的,因此开释锁,准备返回用户态。

13) 用户进程代码开始实行,此时recv等方法返回的便是从内核拷贝的字节数。

吸收报文场景二

 第二张图给出了第二个场景,这里涉及了 prequeue行列步队。
用户进程调用recv方法时,socket行列步队中没有任何报文,而socket是壅塞的,以是进程就寝了。
然后操作系统收到了报文,此时 prequeue行列步队开始产生浸染。
该场景中, tcp_low_latency为默认的0,套接字socket的 SO_RCVLOWAT是默认的1,仍旧是壅塞socket,如下图。

 个中1,2,3步骤的处理和之前一样。
我们直接从第四步开始。

4) 由于此时 receive, prequeue和 backlog行列步队都为空,以是没有拷贝一个字节到用户内存中。
而socket的配置哀求至少拷贝 SO_RCVLOWAT也便是1字节的报文,因此进入壅塞式套接字的等待流程。
最历久待韶光为 SO_RCVTIMEO指定的韶光。
socket在进入等待前会开释socket锁,会使第五步中,新来的报文不再只能进入 backlog行列步队。

5) 接到S1报文,将其加入 prequeue行列步队中。

6) 插入到 prequeue行列步队后,会唤醒在socket上休眠的进程。

7) 用户进程被唤醒后,重新获取socket锁,此后再吸收到的报文只能进入 backlog行列步队。

8) 进程先检讨 receive行列步队,当然仍旧是空的;再去检讨 prequeue行列步队,创造有报文S1,恰好是正在等待序号的报文,于是直接从 prequeue行列步队中拷贝到用户内存,再开释内核中的这个报文。

9) 目前已经拷贝了一个字节的报文到用户内存,检讨这个长度是否超过了最低阈值,也便是len和 SO_RCVLOWAT的最小值。

10) 由于 SO_RCVLOWAT利用了默认值1,拷贝字节数大于最低阈值,准备返回用户态,顺便会查看一下backlog行列步队中是否有数据,此时没有,以是准备放回,开释socket锁。

11) 返回用户已经拷贝的字节数。

吸收报文场景三

 在第三个场景中,系统参数 tcp_low_latency为1,socket上设置了 SO_RCVLOWAT属性值。
做事器先收到报文S1,但是其长度小于 SO_RCVLOWAT。
用户进程调用 recv方法读取,虽然读取到了一部分,但是没有到达最小阈值,以是进程就寝了。
与此同时,在就寝前吸收的乱序的报文S3直接进入 backlog行列步队。
然后,报文S2到达,由于没有利用 prequeue行列步队(由于设置了tcplowlatency),而它起始序号正是下一个待拷贝的值,以是直接拷贝到用户内存中,统共拷贝字节数已知足 SO_RCVLOWAT的哀求!
末了在返回用户前把 backlog行列步队中S3报文也拷贝给用户。

1) 吸收到报文S1,正是准备吸收的报文序号,因此,将它直接加入到有序的 receive行列步队中。

2) 将系统属性 tcp_low_latency设置为1,表明做事器希望程序能够及时的吸收到TCP报文。
用户调用的 recv吸收壅塞socket上的报文,该socket的 SO_RCVLOWAT值大于第一个报文的大小,并且用户分配了足够大的长度为len的内存。

3) 调用 tcp_recvmsg方法来完成吸收事情,先锁住socket。

4) 准备处理内核各个吸收行列步队中的报文。

5) receive行列步队中有报文可以直接拷贝,其大小小于len,直接拷贝到用户内存。

6) 在进行第五步的同时,内核又吸收到S3报文,此时socket被锁,报文直接进入 backlog行列步队。
这个报文并不是有序的。

7) 在第五步时,拷贝报文S1到用户内存,它的大小小于 SO_RCVLOWAT的值。
由于socket是壅塞型,以是用户进程进入就寝状态。
进入就寝前,会先处理 backlog行列步队的报文。
由于S3报文是失落序的,以是进入out_of_order行列步队。
用户进程进入休眠状态前都会先处理一下 backlog行列步队。

8) 进程休眠,直到超时或者 receive行列步队不为空。

9) 内核吸收到报文S2。
把稳,此时由于打开了 tcp_low_latency标志位,以是报文是不会进入 prequeue行列步队等待进程处理。

10) 由于报文S2正是要吸收的报文,同时,一个用户进程在休眠等待该报文,以是直接将报文S2拷贝到用户内存。

11) 每处理完一个有序报文后,无论是拷贝到 receive行列步队还是直接复制到用户内存,都会检讨 out_of_order行列步队,看看是否有报文可以处理。
报文S3拷贝到用户内存,然后唤醒用户进程。

12) 唤醒用户进程。

13) 此时会检讨已拷贝的字节数是否大于 SO_RCVLOWAT,以及 backlog行列步队是否为空。
两者皆知足,准备返回。

 总结一下四个行列步队的浸染。
receive行列步队是真正的吸收行列步队,操作系统收到的TCP数据包经由检讨和处理后,就会保存到这个行列步队中。
backlog是“备用行列步队”。
当socket处于用户进程的高下文时(即用户正在对socket进行系统调用,如recv),操作系统收到数据包时会将数据包保存到 backlog行列步队中,然后直接返回。
prequeue是“预存行列步队”。
当socket没有正在被用户进程利用时,也便是用户进程调用了read或者recv系统调用,但是进入了就寝状态时,操作系统直接将收到的报文保存在 prequeue中,然后返回。
out_of_order是“乱序行列步队”。
行列步队存储的是乱序的报文,操作系统收到的报文并不是TCP准备吸收的下一个序号的报文,则放入 out_of_order行列步队,等待后续处理。

参考

http://www.voidcn.com/article/p-gzmjmmna-dn.htmlhttps://blog.csdn.net/russell_tao/article/details/9950615https://ylgrgyq.github.io/2017/08/01/linux-receive-packet-3/
标签:

相关文章

CMS采集技术在信息时代的重要性与应用

随着信息技术的飞速发展,大数据、云计算、人工智能等新技术层出不穷。在这个信息爆炸的时代,如何有效地采集、整合、处理和利用信息成为了...

Web前端 2024-12-26 阅读0 评论0

IT咨询顾问,企业数字化转型的关键推手

在信息化、数字化时代,企业数字化转型已成为必然趋势。IT咨询顾问作为企业数字化转型的关键推手,扮演着举足轻重的角色。本文将从IT咨...

Web前端 2024-12-26 阅读0 评论0

CMS证书酒,品质与品位的象征

在当今社会,随着人们生活水平的提高,对酒品的要求也越来越高。一款好的酒,不仅要有上乘的口感,更要有深厚的文化底蕴。而CMS证书酒,...

Web前端 2024-12-26 阅读0 评论0

CMS系统仿优设,打造卓越网站体验的方法

随着互联网的快速发展,网站已成为企业展示形象、拓展业务的重要平台。如何打造一个既能满足用户需求,又能体现企业品牌价值的网站,成为了...

Web前端 2024-12-26 阅读0 评论0

CMS老年代,技术创新与产业升级的先锋力量

随着我国经济的快速发展,信息技术在各个领域的应用日益广泛,其中CMS(内容管理系统)在互联网产业中扮演着举足轻重的角色。特别是在老...

Web前端 2024-12-26 阅读0 评论0