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

前几天我在新浪微博上出了两道有关 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 并发连接数”是没有意义的,因为连接数基 本上是要多少有多少。更有意义的性能指标或许是:“每秒钟收发多少条消息”、“每秒钟收发多少字 节的数据”、“支持多少个活动的并发客户”等等。

时间: 2024-12-03 10:47:35

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

图解TCP建立连接全过程

TCP是因特网中的传输层协议,使用三次握手协议建立连接,下面是TCP建立连接的全过程. 上图画出了TCP建立连接的过程.假定主机A是TCP客户端,B是服务端.最初两端的TCP进程都处于CLOSED状态.图中在主机下面的是TCP进程所处的状态.A是主动打开连接,B是被动打开连接. 首先A向B发出连接请求报文段,这时首部中的同步位SYN=1,同时选择一个初始序号seq=x.TCP规定,SYN报文段不能携带数据,但要消耗掉一个序号.这时,A进入SYN-SENT状态. B收到请求后,向A发送确认.在确认

Delphi中多进程解决datasnap支持的tcp长连接数量少的问题

对于实时采集数据的项目,应用场景比如是这样的:5000客户端,每个客户端每隔500MS要给服务器上传一次数据. 大家知道,像INDY这种阻塞型的通信控件,所能支持的TCP长连接的一般地不能超过1000的数量(如果想要维持稳定运行的话). 原因是大家都晓得的,阻塞方式会为每一个SOCKET连接创建一个新的线程为之服务,而WINDOWS单个进程理论上允许最多的线程数量是2048个, 实际当中要少得多才行. 有人说可以用WINDOWS的IOCP通信模型解决,诚然!但IOCP编程过于复杂. 有人说,可以

MSSQL通过端口1433连接到主机127.0.0.1的TCP/IP连接失败

环境:SQLServer 2008 R2 + MyEclipse 6.5 + JDK 1.6.24 问题: Java通过JDBC连接 SQLServer 2008,出现如下问题:通过端口 1433 连接到主机 127.0.0.1 的 TCP/IP 连接失败.错误: "connect timed out.请验证连接属性,并检查 SQL Server 的实例正在主机上运行,且在此端口接受 TCP/IP 连接,还要确保防火墙没有阻止到此端口的 TCP 连接. 解决: 1. 打开 SQLServer 配

TCP断开连接过程详解

上次我们讲了TCP三次握手建立连接的过程,今天我们结合双方状态的改变来讲讲TCP断开连接的过程:TCP四次挥手. 数据传输结束后,通信的双方都可释放连接.现在A和B都处于ESTABLISHED状态.A的应用程序先向TCP发出连接释放报文段,主动关闭TCP连接.A把连接释放报文段的首部FIN置为1,序号seq=u,它等于前面已传送过的数据的最后一个字节的序号加1.这时A进入FIN-WAIT-1状态,等待B的确认. B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v

tcp短连接TIME_WAIT问题解决方法大全(1)——高屋建瓴

tcp连接是网络编程中最基础的概念,基于不同的使用场景,我们一般区分为"长连接"和"短连接",长短连接的优点和缺点这里就不详细展开了,有心的同学直接去google查询,本文主要关注如何解决tcp短连接的TIME_WAIT问题. 短连接最大的优点是方便,特别是脚本语言,由于执行完毕后脚本语言的进程就结束了,基本上都是用短连接.但短连接最大的缺点是将占用大量的系统资源,例如:本地端口.socket句柄.导致这个问题的原因其实很简单:tcp协议层并没有长短连接的概念,因此

服务器-TCP/IP 连接异常 大牛快来

问题描述 TCP/IP 连接异常 大牛快来 问题是这样的 服务器-客户端 TCP连接 出现下面两种情况 1: 在服务器这边连接的状态是establish 而在client 这端 没有任何关于连接的信息 2:客户端这边连接的状态是establish 而在service 这点 没有关于 连接的任何信息 以上两种情况 出现的环境是 1 客户端 和服务器多是在虚拟机环境下. 2 而且这个时候 客户端 和服务器 还多没有退出 不知道 什么情况下 会出现这种情况 大家 帮忙讨论讨论 牛人 牛人 快出现 我所

android-Android与服务器采用tcp长连接传输数据的弊端

问题描述 Android与服务器采用tcp长连接传输数据的弊端 在做一个项目,有一个实时的统计的需求,想用tcp建立长连接来实现,但是感觉长连接会很耗电,有没有大神做过这方面的研究,想知道一下使用tcp长连接的利弊,会有哪些用户体验上面的影响 解决方案 最主要的就是费电,其次可能用户感觉不到什么,但是如果安装了电量统计,可能会有影响.建议稍微有个延迟,在省电方面会好些. 解决方案二: 累死你的程序,占用资源,你的其他功能还怎么运行

Java连接sqlserver2005到主机的TCP/IP连接失败问题

  今天用Java连接SqlServer2005怎么也连不上,整理了一下把它贴出来希望能帮到大家.   连接SqlServer2005很有可能遇到这个问题: com.microsoft.sqlserver.jdbc.SQLServerException: 到主机的TCP/IP 连接失败. java.net.ConnectException:   Connection   refused: connect     思路一 首先看一下sqlserver2000与sqlserver2005驱动与url

tcp 负载均衡,tcp长连接的重复使用

问题描述 tcp 负载均衡,tcp长连接的重复使用 问题: 1.我有很多终端设备(非手机)通过TCP连接负载均衡服务器,并被分配到相应的后端服务器(通过端口连接,但这些后端服务器除了运行mina TCP长连接服务也提供http服务),请问这些终端设备是否直接与后端服务器TCP连接,而非与负载均衡服务连接? 2.我想通过手机APP发送消息给上述问题中的终端设备(例如设备 A),手机App是通过http负载均衡到上述的后端服务器,问题就是我手机APP如何找到后端服务器(这个服务器有TCP连接 连接着