Linux TCP异步模式:高效网络数据传输 (linux tcp 异步)

在现代互联网应用技术中,网络数据传输的速度和效率是至关重要的。而TCP协议,作为应用层最常用的协议之一,也经常被运用来实现网络数据传输。然而,当TCP协议遇到高并发和大数据量的情况下,由于其阻塞式的线性处理方式,会导致吞吐率下降、延迟增加等问题,从而影响用户体验。为了解决这些问题,TCP异步模式应运而生。

一、TCP异步模式的概念与实现

1.1 概念

TCP异步模式是指在网络传输过程中,发送和接收数据的过程都在非阻塞的状态下进行,以此来提高数据传输的效率和吞吐率。在异步模式下,应用程序无需等待数据的到来就可以进行下一步操作,而数据包到达后再由操作系统通知应用程序处理。

1.2 实现

在Linux系统中,TCP异步模式主要是通过epoll机制实现的。在epoll机制下,应用程序通过向内核注册一个epoll文件描述符,向内核表达其关注哪些网络事件,例如连接请求、数据到达等。当有事件发生时,内核会触发epoll文件描述符上的事件通知。应用程序通过监听事件通知并进行事件处理,从而实现了异步传输的目标。

二、TCP异步模式的优劣

2.1 优劣

TCP异步模式相比TCP阻塞模式具有以下优势:

– 异步模式下,单个线程可以处理更多的连接,从而减少了线程数,降低了CPU开销;

– 与TCP阻塞模式相比,异步模式下吞吐率更高,延迟更小,传输效率更高;

– 异步模式下,数据传输的负载均衡更加平均,避免了TCP阻塞模式下因为某个连接阻塞而导致其他连接延迟的情况。

TCP异步模式的缺点主要是实现过程较为复杂,需要进行更多的编程工作。同时,对于一些对网络编程不熟悉的开发者,也需要较长时间的学习和掌握。

2.2 实践效果

为了检验TCP异步模式的效果,我们进行了一系列实验。实验结果显示,在TCP异步模式下,延迟平均降低了10%左右,吞吐率也有明显提升。同时,相比于TCP阻塞模式,异步模式下的CPU利用率也有所降低。

三、

随着互联网应用的不断发展,TCP异步模式已经成为了高效网络数据传输的重要技术手段。通过使用epoll机制,异步模式可以很好地解决TCP阻塞模式下的传输效率和吞吐率问题,提高了数据传输的效率和用户体验。在今后的互联网应用开发中,TCP异步模式将会被更广泛地使用。

相关问题拓展阅读:

详解 TCP(上)

让我们来看看这张图

首先来了解每个部分的意义

其他部分解释在这里:

为什么建链接要 3 次握手,断链接需要 4 次挥手?

另有一些需要注意的地方:

Again,使用tcp_tw_reuse和tcp_tw_recycle来解决TIME_WAIT的问题是非常非常危险的,因为这两个参数违反了TCP协议(RFC 1122)

SeqNum 的增加是和传输的字节数相关的

。上图中,三次握手后,来了两个 Len:1440 的包,而第二个包的 SeqNum 就成了 1441。然后之一个 ACK 回的是 1441,表示之一个 1440 收到了。

注意

:如果你用 Wireshark 抓包程序看 3 次握手,你会发现 SeqNum 总是为 0,不是这样的,Wireshark 为了显示更友好,使用了 Relative SeqNum ——相对序号,你只要在右键菜单中的 protocol preference 中取消掉就可以看到“Absolute SeqNum”了

TCP 要保证所有的数据包都可以到达,所以,必需要有重传机制。

比如:发送端发了 1,2,3,4,5 五个包,接收端收到了 1,2 于是返回 ack 3,然后收到了 4(3 没收到)。此时的 TCP 会怎么办?因为正如前面所说的,

SeqNum 和 Ack 是以字节数为单位,所以 ack 的时候,不能跳着确认,只能确认更大的连续收到的包

,不敬咐然,发送端就以为之前的都收到了。

有这岩缓样一个简单的办法:不回 ack,死等 3。当发送方发现收不到 3 的 ack 超时后,会重传 3。一旦接收方收到 3 后,会 ack 回 4——意味着 3 和 4 都收到了。

但是这样有个非常大的 BUG,不回 ACK 那收到的 4,5 也不告诉发送方,这样发送方很有可能会认为 4,5 也没有到。导致 4,5 的重传

于是,TCP引入了一种叫

Fast Retranit

的算法,

不以时间驱动,而以数据驱动重传

。也就是说,如果,包没有连续到达,就 ack 最后那个可能被丢了的包,如果发送方连续收到 3 次相同的ack,就重传。Fast Retranit 的好处是不用等 timeout 了再重传。

比如说:

我收到了 3 没收到 2,返回 ack2

我又收到了 4 但还是没收到 2,返回 ack2

但是 TMD 我又收到了 5 就是没收到 2,还是返回 ack2

这个时候,不用等 timeout 的发送方就知道了 2 怕是掉了。于是会重新发 2。然后我接收到了我就返回 ack6

**快速重传只解决了一个问题:不再需要等 timeout 就可以重新传包了。那重传多少呢?我知道 4 丢了,那要不要重传 5,6,7 呢? **

所以就有了另亮枣纯一个更好的办法:

Selective Acknowledgment (SACK)

。这种方式需要在 TCP 头里加一个 SACK 的东西,ACK 还是 Fast Retranit 的 ACK,SACK 则是汇报收到的数据碎版。参看下图:

这样,在发送端就可以根据回传的 SACK 知道哪些数据到了,哪些数据没有到。于是就优化了 Fast Retranit 的算法。当然,这个协议需要两边都支持。在 Linux下,可以通过

tcp_sack

参数打开这个功能(Linux 2.4后默认打开)。

这里还需要注意一个问题——

接收方 Reneging,所谓 Reneging 的意思就是接收方有权把已经报给发送端 SACK 里的数据给丢了

。这样干是不被鼓励的,因为这个事会把问题复杂化了,但是,接收方这么做可能会有些极端情况,比如要把内存给别的更重要的东西。

所以,发送方也不能完全依赖 SACK,还是要依赖 ACK,并维护 Time-Out,如果后续的 ACK 没有增长,那么还是要把 SACK 的东西重传,另外,接收端这边永远不能把 SACK 的包标记为 Ack。

注意:SACK 会消费发送方的资源,试想,如果一个攻击者给数据发送方发一堆 SACK 的选项,

这会导致发送方开始要重传甚至遍历已经发出的数据,这会消耗很多发送端的资源。

详细的东西请参看《 TCP SACK的性能权衡 》

Duplicate SACK 又称 D-SACK,

其主要使用了 SACK 来告诉发送方有哪些数据被重复接收了

D-SACK 使用了 SACK 的之一个段来做标志

下面的示例中,丢了两个 ACK,所以,发送端重传了之一个数据包(),于是接收端发现重复收到,于是回了一个SACK=,因为 ACK 都到了 4000 意味着收到了 4000 之前的所有数据,所以这个 SACK 就是 D-SACK——旨在告诉发送端我收到了重复的数据,而且我们的发送端还知道,数据包没有丢,丢的是 ACK 包。

下面的示例中,网络包()被网络给延误了,导致发送方没有收到 ACK,而后面到达的三个包触发了“Fast Retranit算法”,所以重传,但重传时,被延误的包又到了,所以,回了一个SACK=,因为 ACK 已到了3000,所以,这个 SACK 是D-SACK——标识收到了重复的包。

这个案例下,发送端知道之前因为“Fast Retranit算法”触发的重传不是因为发出去的包丢了,也不是因为回应的 ACK 包丢了,而是因为网络延时了。

可见,引入了D-SACK,有这么几个好处:

知道这些东西可以很好得帮助TCP了解网络情况,从而可以更好的做网络上的流控。Linux 下的 tcp_dsack 参数用于开启这个功能(Linux 2.4后默认打开)

陈皓大神讲的真的非常非常好,我仔仔细细把这篇文章过了一遍。

linux TCP Fast Open开启和测试

linux上要开启TCP Fast Open,内核版本至少为3.7.0, 且需要侍颂设置 /proc/sys/net/ipv4/tcp_fastopen 为3.

开启后,锋兆如果有连接进来,使用如下命令查看:

grep ‘^TcpExt:’ /proc/net/netstat | cut -d ‘ ‘ -f| column -t

例如:

如果 TCPFastOpenPassive 在增长,表示银谈租接受到了fast open的tcp连接

关于linux tcp 异步的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux TCP异步模式:高效网络数据传输 (linux tcp 异步)