关于 TCP 并发连接的几个思考题与试验

网络通信原理之TCP,UDP,QUIC 此篇讲述下计算机网络体系结构及网络通信模型、TPC/IP协议、UDP 和 QUIC。我们所有的工作生活都离不开网络,那么什么是网络呢?看了定义之后应该就能理解,就是通过网线,卫星基站等将各个电脑等设备连接起来,构成互联网,实现文件共享和信息传递的功能的系统。 OSI:open system interconnection(开放互连系统参考模型),是对各种协议提供标准化的一种框架模型,它给出了7层的理论模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 根据该模型演绎出TCP/IP模型,这是我 阅读详情

陈硕 (giantchen AT gmail)

blog.youkuaiyun.com/Solstice

前几天我在新浪微博上出了两道有关 TCP 的思考题,引发了一场讨论 http://weibo.com/1701018393/eCuxDrta0Nn 。

第一道初级题目是:

有一台机器,它有一个 IP,上面运行了一个 TCP 服务程序,程序只侦听一个端口,问:从理论上讲(只考虑 TCP/IP 这一层面,不考虑IPv6)这个服务程序可以支持多少并发 TCP 连接?答 65536 上下的直接刷掉。

具体来说,这个问题等价于:有一个 TCP 服务程序的地址是 1.2.3.4:8765,问它从理论上能接受多少个并发连接?

第二道进阶题目是:

一台被测机器 A,功能同上,同一交换机上还接有一台机器 B,如果允许 B 的程序直接收发以太网 frame,问:让 A 承担 10 万个并发 TCP 连接需要用多少 B 的资源?100万个呢?

从讨论的结果看,很多人做出了第一道题,而第二道题几乎无人问津。

 

这里先不公布答案(第一题答案见文末),让我们继续思考一个本质的问题:一个 TCP 连接要占用多少系统资源。

在现在的 Linux 操作系统上,如果用 socket()/connect() 或 accept() 来创建 TCP 连接,那么每个连接至少要占用一个文件描述符(file descriptor)。为什么说“至少”?因为文件描述符可以复制,比如 dup();也可以被继承,比如 fork();这样可能出现系统里边同一个 TCP 连接有多个文件描述符与之对应。据此,很多人给出的第一题答案是:并发连接数受限于系统能同时打开的文件数目的最大值。这个答案在实践中是正确的,却不符合原题意。

 

如果抛开操作系统层面,只考虑 TCP/IP 层面,建立一个 TCP 连接有哪些开销?理论上最小的开销是多少?考虑两个场景:

1. 假设有一个 TCP 服务程序,向这个程序成功发起连接需要做哪些事情?换句话说,如何才能让这个 TCP 服务程序认为有客户连接到了它(让它的 accept() 调用正常返回)?

2. 假设有一个 TCP 客户端程序,让这个程序成功建立到服务器的连接需要做哪些事情?换句话说,如何才能让这个 TCP 客户端程序认为它自己已经连接到服务器了(让它的 connect() 调用正常返回)?

以上这两个问题问的不是如何编程,如何调用 Sockets API,而是问如何让操作系统的 TCP/IP 协议栈认为任务已经成功完成,连接已经成功建立。

 

学过 TCP/IP 协议,理解三路握手的同学明白,TCP 连接是虚拟的连接,不是电路连接,维持 TCP 连接理论上不占用网络资源(会占用两头程序的系统资源)。只要连接的双方认为 TCP 连接存在,并且可以互相发送 IP packet,那么 TCP 连接就一直存在。

对于问题 1,向一个 TCP 服务程序发起一个连接,客户端(为明白起见,以下称为 faketcp 客户端)只需要做三件事情(三路握手):

1a. 向 TCP 服务程序发一个 IP packet,包含 SYN 的 TCP segment

1b. 等待对方返回一个包含 SYN 和 ACK 的 TCP segment

1c. 向对方发送一个包含 ACK 的 segment

在做完这三件事情之后,TCP 服务器程序会认为连接已建立。而做这三件事情并不占用客户端的资源(?),如果faketcp 客户端程序可以绕开操作系统的 TCP/IP 协议栈,自己直接发送并接收 IP packet 或 Ethernet frame 的话。换句话说,faketcp 客户端可以一直重复做这三件事件,每次用一个不同的 IP:PORT,在服务端创建不计其数的 TCP 连接,而 faketcp 客户端自己毫发无损。很快我们将看到如何用程序来实现这一点。

对于问题 2,为了让一个 TCP 客户端程序认为连接已建立,faketcp 服务端只需要做两件事情:

2a. 等待客户端发来的 SYN TCP segment

2b. 发送一个包含 SYN 和 ACK 的 TCP segment

2c. 忽视对方发来的包含 ACK 的 segment

在做完这两件事情(收一个 SYN、发一个 SYN+ACK)之后,TCP 客户端程序会认为连接已建立。而做这三件事情并不占用 faketcp 服务端的资源(?)换句话说,faketcp 服务端可以一直重复做这两件事件,接受不计其数的 TCP 连接,而 faketcp 服务端自己毫发无损。很快我们将看到如何用程序来实现这一点。

 

基于对以上两个问题的分析,说明单独谈论“TCP 并发连接数”是没有意义的,因为连接数基本上是要多少有多少。更有意义的性能指标或许是:“每秒钟收发多少条消息”、“每秒钟收发多少字节的数据”、“支持多少个活动的并发客户”等等。

faketcp 的程序实现

代码见: https://github.com/chenshuo/recipes/tree/master/faketcp 可以直接用 make 编译

为了验证我上面的说法,我写了几个小程序来实现 faketcp,这几个程序可以发起或接受不计其数的 TCP 并发连接,并且不消耗操作系统资源,连动态内存分配都不会用到。

我家里有一台运行 Ubuntu Linux 10.04 的 PC 机,hostname 是 atom,所有的试验都在这上面进行。

家里试验环境的网络配置是:

net

陈硕在《谈一谈网络编程学习经验》中曾提到“可以用 TUN/TAP 设备在用户态实现一个能与本机点对点通信的 TCP/IP 协议栈”,这次的试验正好可以用上这个办法。

试验的网络配置是:

tun

具体做法是:在 atom 上通过打开 /dev/net/tun 设备来创建一个 tun0 虚拟网卡,然后把这个网卡的地址设为 192.168.0.1/24,这样 faketcp 程序就扮演了 192.168.0.0/24 这个网段上的所有机器。atom 发给 192.168.0.2~192.168.0.254 的 IP packet 都会发给 faketcp 程序,faketcp 程序可以模拟其中任何一个 IP 给 atom 发 IP packet。

程序分成几步来实现。

第一步:实现 icmp echo 协议,这样就能 ping 通 faketcp 了。

代码见 https://github.com/chenshuo/recipes/blob/master/faketcp/icmpecho.cc

其中响应 icmp echo request 的函数在 https://github.com/chenshuo/recipes/blob/master/faketcp/faketcp.cc#L57 这个函数在后面的程序中也会用到。

运行方法,打开 3 个命令行窗口:

1. 在第 1 个窗口运行 sudo ./icmpecho ,程序显示

allocted tunnel interface tun0

2. 在第 2 个窗口运行

$ sudo ifconfig tun0 192.168.0.1/24

$ sudo tcpdump -i tun0

3. 在第 3 个窗口运行

$ ping 192.168.0.2

$ ping 192.168.0.3

$ ping 192.168.0.234

发现每个 192.168.0.X 的 IP 都能 ping 通。

 

第二步:实现拒绝 TCP 连接的功能,即在收到 SYN TCP segment 的时候发送 RST segment。

代码见 https://github.com/chenshuo/recipes/blob/master/faketcp/rejectall.cc

运行方法,打开 3 个命令行窗口,头两个窗口的操作与前面相同,运行的 faketcp 程序是 ./rejectall

3. 在第 3 个窗口运行

$ nc 192.168.0.2 2000

$ nc 192.168.0.2 3333

$ nc 192.168.0.7 5555

发现向其中任意一个 IP 发起的 TCP 连接都被拒接了。

 

第三步:实现接受 TCP 连接的功能,即在收到SYN TCP segment 的时候发回 SYN+ACK。这个程序同时处理了连接断开的情况,即在收到 FIN segment 的时候发回 FIN+ACK。

代码见 https://github.com/chenshuo/recipes/blob/master/faketcp/acceptall.cc

运行方法,打开 3 个命令行窗口,步骤与前面相同,运行的 faketcp 程序是 ./acceptall。这次会发现 nc 能和 192.168.0.X 中的每一个 IP 每一个 PORT 都能连通。还可以在第 4 个窗口中运行 netstat –tpn ,以确认连接确实建立起来了。如果在 nc 中输入数据,数据会堆积在操作系统中,表现为 netstat 显示的发送队列(Send-Q)的长度增加。

 

第四步:在第三步接受 TCP 连接的基础上,实现接收数据,即在收到包含 payload 数据 的 TCP segment 时发回 ACK。

代码见 https://github.com/chenshuo/recipes/blob/master/faketcp/discardall.cc

运行方法,打开 3 个命令行窗口,步骤与前面相同,运行的 faketcp 程序是 ./acceptall。这次会发现 nc 能和 192.168.0.X 中的每一个 IP 每一个 PORT 都能连通,数据也能发出去。还可以在第 4 个窗口中运行 netstat –tpn ,以确认连接确实建立起来了,并且发送队列的长度为 0。

这一步已经解决了前面的问题 2,扮演任意 TCP 服务端。

 

第五步:解决前面的问题 1,扮演客户端向 atom 发起任意多的连接。

代码见 https://github.com/chenshuo/recipes/blob/master/faketcp/connectmany.cc

这一步的运行方法与前面不同,打开 4 个命令行窗口。

1. 在第 1 个窗口运行 sudo ./connectmany 192.168.0.1 2007 1000 ,表示将向 192.168.0.1:2007 发起 1000 个并发连接。

程序显示

allocted tunnel interface tun0
press enter key to start connecting 192.168.0.1:2007

 

2. 在第 2 个窗口运行

$ sudo ifconfig tun0 192.168.0.1/24

$ sudo tcpdump -i tun0

3. 在第 3 个窗口运行一个能接收并发 TCP 连接的服务程序,可以是 httpd,也可以是 muduo 的 echo 或 discard 示例,程序应 listen 2007 端口。

4. 回到第 1 个窗口中敲回车,然后在第 4 个窗口中用 netstat -tpn 来观察并发连接。

 

有兴趣的话,还可以继续扩展,做更多的有关 TCP 的试验,以进一步加深理解,验证操作系统 TCP/IP 协议栈面对不同输入的行为。甚至可以按我在《谈一谈网络编程学习经验》中提议的那样,实现完整的 TCP 状态机,做出一个简单的 mini tcp stack。

 

第一道题的答案:

在只考虑 IPv4 的情况下,并发数的理论上限是 2**48。考虑某些 IP 段被保留了,这个上界可适当缩小,但数量级不变。实际的限制是操作系统全局文件描述符的数量,以及内存大小。

一个 TCP 连接有两个 end points,每个 end point 是 {ip, port},题目说其中一个 end point 已经固定,那么留下一个 end point 的自由度,即 2 ** 48。客户端 IP 的上限是 2**32 个,每个客户端IP发起连接的上限是 2**16,乘到一起得理论上限。

即便客户端使用 NAT,也不影响这个理论上限。(为什么?)

 

在真实的 Linux 系统中,可以通过调整内核参数来支持上百万并发连接,具体做法见:

http://urbanairship.com/blog/2010/09/29/linux-kernel-tuning-for-c500k/

http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-3

 

(.完.)

UE4/5编译报错MSB3073终极解决指南:从路径检查到MSVC版本降级 本文针对UE4/5开发中常见的MSB3073编译报错,提供了一套从根源到实战的终极解决指南。文章系统性地讲解了错误成因,并分层次指导排查路径字符、环境变量、MSVC版本兼容性、权限冲突等核心问题,重点介绍了通过降级MSVC编译器版本等关键操作来彻底解决此编译难题。 阅读详情

相关推荐

【KDD2024】ShapeFormer:用于多元时间序列分类的Shapelet Transformer

多元时间序列分类(MTSC)因其在现实世界中的广泛应用而吸引了大量研究关注。最近,Transformer在MTSC中取得了先进的性能。然而,

m0_52597077的博客 4747

TCP伪装

给UDP穿个外套吧

Fireplusplus的博客 2338

STM32+W5500实战:5分钟搞定FreeModbus TCP移植(附完整代码)

本文详细介绍了如何在STM32微控制器上,结合W5500以太网芯片,快速完成FreeModbus TCP协议栈的移植,构建稳定可靠的工业级Modbus TCP服务器。内容涵盖硬件连接、软件架构、驱动适配、核心移植代码实现及调试优化技巧,旨在提供可直接应用于实际项目的完整解决方案。

life6的博客 879

Phantun开发者指南:如何基于fake-tcp构建自己的隧道工具

Phantun是一个强大的开源工具,它能够将UDP流转换为可通过三层和四层(NAPT)防火墙/NAT的(伪)TCP流。本指南将向开发者展示如何基于Phantun的fake-tcp库构建自己的隧道工具,让你的网络应用轻松穿透各种网络限制。 ## 了解fake-tcp库 fake-tcp是Phantun项目的核心组件,它是一个基于TUN接口的用户空间异步高性能TCP协议栈,允许以最小开销进行面向数

gitblog_00455的博客 841

【已验证】基于STM32F407与AD9833的幅频特性测试装置设计与实现

本文详细介绍了基于STM32F407微控制器和AD9833 DDS芯片的低成本幅频特性测试装置设计与实现方法。通过扫频原理,该装置能自动生成正弦波信号,测量滤波器等电路的输出幅度变化,并在LCD屏幕或示波器上绘制幅频特性曲线。文章提供了从硬件选型、CubeMX工程配置、关键驱动代码编写到数据处理与可视化的完整教程,帮助电子爱好者与工程师快速搭建实用的滤波器测试工具。

weixin_35649491的博客 120

基于STM32F103C8T6的循迹避障小车完整制作过程(详细)----上篇(第123点)

基于STM32F103C8T6的循迹避障小车完整制作过程 由于本人的一个小项目,要做一个基于STM32的循迹避障小车,前后花了约1周的时间,这个过程种也参考了很多大神分享的资料,学到很多的东西。但是资料都比较分散,有些东西也不好找,在这里就想把自己制作小车的一个整体过程记录分享一下,希望能够帮到你。 我自己也算是一个小白,之前有做过 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎...

weixin_43924857的博客 14万+

【免费下载】 FakeHTTP:将TCP连接隐藏为HTTP协议的工具

在网络安全领域,保护数据传输的安全性至关重要。FakeHTTP 是一个开源项目,其核心功能是将所有的 TCP 连接伪装成 HTTP 协议,从而在不改变原有数据内容的情况下,增加网络传输的安全性。项目基于 Netfilter Queue (NFQUEUE) 实现,适用于需要对数据传输进行加密和混淆的场景。 ## 项目技术分析 FakeHTTP 使用了 Netfilter Queue,这是Linu

gitblog_01127的博客 1371

015、架构_配置文件_管理节点(proxymanager.ini)

该配置文件中的参数在后台配置,两种生效方式:*所有参数重启生效。*部分参数可以使用工具dbtool动态生效。动态生效命令为:dbtool-pm-load-config。配置文件“proxymanager.ini”用于设置元数据管理模块的信息。文件路径为“~/etc”。配置文件“proxymanager.ini”是普通的文本文件。默认值proxymanager-alarmconfutf8.txt。配置错误或不配置,PM无法连接MDS,无法服务。获取元数据失败超时处理时间。异常时请求启动对等回滚。

Oracle/MySQL 到 国产信创数据库|迁移 · 调优 · 信创替换 329

一些Git Repo

单机8核并发10个client,CPU全部打满的情况下,QPS有12-15W左右。如果CPU频率、核数更高更多的话,QPS还会往上走一些。Client跟Server都在。自己写的魔兽世界钓鱼脚本,10.0初期钓鱼成功率90%以上。现在关服了暂时没用了。自己写的模拟柜台跟客户端API,可以提供基本的client跟server通讯模型。尝试把UDP的包伪装成TCP包,再发送到Internet。自己写的一个伪装包测试。环境下跑过,没啥问题。

nia305的博客 675

机器学习实战7-基于机器学习算法预测相亲成功率

大家好,我是微学AI,今天给大家介绍一下机器学习实战7-基于机器学习算法预测相亲成功率,随着社会的发展,大家都忙于事业,对自己的终身大事就耽搁了,相亲是一种传统的寻找伴侣的方式,随着时代的发展,相亲的方式也在不断地改变。在这个过程中,了解相亲双方的信息以及预测相亲是否成功变得越来越重要。本文将介绍如何使用随机森林算法对相亲成功进行预测,通过分析男女双方的房子、车子、长相、家庭条件、父母情况、生活习惯、学历、性格、兴趣等因素,来预测相亲是否成功。

微学AI的博客 3034

C++ Qt6 qml CMakeLists.txt如何添加qrc文件

本文介绍了在Qt6项目中如何通过CMake管理QML图片资源。相比Qt5的qmake,CMake需要手动创建qrc文件并配置CMakeLists.txt。关键步骤包括:1)创建resources.qrc文件并添加图片资源;2)在CMakeLists.txt中设置CMAKE_AUTORCC为ON开启自动资源处理;3)使用qt_add_resources将qrc文件绑定到项目。配置完成后,可通过"qrc:alias"方式引用资源图片,解决了相对路径管理复杂的问题。

琅嬛福地 1453

关于 TCP 并发连接的几个思考题与试验 ——陈硕

陈硕 (giantchen AT gmail) blog.youkuaiyun.com/Solstice 前几天我在新浪微博上出了两道有关 TCP 的思考题,引发了一场讨论 http://weibo.com/1701018393/eCuxDrta0Nn 。 第一道初级题目是: 有一台机器,它有一个 IP,上面运行了一个 TCP 服务程序,程序只侦听一个端口,问:从理论上讲(只考虑 TCP/IP 这

likelikebing的专栏 954

FPGA信号处理系列文章——分数倍插值抽取滤波器(一)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 FPGA信号处理系列文章——分数倍插值抽取滤波器(一)前言信号流matlab模型频谱示意图分析总结 前言 变采样率滤波器不仅仅存在整数倍插值和整数倍抽取的情况,还会存在分数倍插值抽取的情况。那这种情况下要怎么处理呢 信号流 分数倍插值抽取滤波器的信号流是什么?信号先进行插值,再进行FIR滤波,最后进行抽取 matlab模型 %signal 定点化数据输入 coeff_val_fir = importdata('fir.coe'); si

gzy0506的博客 1万+

关于 TCP 并发连接的几个思考题与试验GOOD

http://blog.youkuaiyun.com/solstice/article/details/6579232 陈硕 (giantchen AT gmail) blog.youkuaiyun.com/Solstice 前几天我在新浪微博上出了两道有关 TCP 的思考题,引发了一场讨论 http://weibo.com/1701018393/eCuxDrta0Nn 。 第一道初级题目是:

Baple的专栏 1350

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 附录D 关于TCP并发连接的几个思考题与试验

换句话说,faketcp客户端可以一直重复做这三件事情,每次用一个不同的IP:PORT,在服务端创建不计其数的TCP连接,而faketcp客户端自己毫发无损。有兴趣的话,还可以继续扩展,做更多的有关TCP的试验,以进一步加深理解,验证操作系统的TCP/IP协议栈面对不同输入的行为。第一道初级题目是:有一台机器,它有一个IP,上面运行了一个TCP服务程序,程序只侦听一个端口,问:从理论上讲(只考虑TCP/IP这一层面,不考虑IPv6)这个服务程序可以支持多少并发TCP连接?试验的网络配置如图D-2所示。

tus00000的博客 1116

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

计算机网络

关于 TCP 并发连接的几个思考题与试验 TCP 源端口号与目的端口号: 源端口号与目的端口号, 加上IP首部的源IP地址和目的IP地址唯一确定一个TCP连接 序号: 一次TCP通信(从TCP连接建立到断开)过程中某一个传输方向上的字节流编号 确认号: 仅当ACK标志位1时有效. 表示期望下一个字节的序号 头部长度: 标识TCP头部有多少个32bit(4字节). 因为4位最大能表示15...

weixin_30606461的博客 1045

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

TCP套接字编程

1. tcp 服务端和客户端程序设计: https://www.cnblogs.com/loanhicks/p/7341775.html 2.关于 TCP 并发连接的几个思考题与试验 http://blog.youkuaiyun.com/solstice/article/details/6579232

PHP程序员 - muzihao2014 252
上一篇: Muduo 多线程模型:一个 Sudoku 服务器演变
下一篇: C++ 工程实践(7):iostream 的用途与局限
陈硕
博客等级 码龄26年 1万+粉丝 144原创
评论 20
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值