首页 文章

32位linux上同时进行tcp / ip连接的次数

提问于
浏览
1

我有一个关于实现负载均衡器或执行TCP / IP的TCP / IP服务器程序的具体问题 .

由于端口号为16位,因此在任何给定时间,单个Linux机器上最多只有65536个端口 . TCP / IP需要一个端口号与外界通信 . 1)当客户端 Build 连接时,选择短暂的端口号 . 2)当监听套接字的服务器接受连接时,分配端口号 .

因此,根据我的理解,在任何给定时间,给定计算机上最多只能存在65536个TCP / IP连接 .

那么一些或大多数负载均衡器如何声称200,000或更多并发连接呢?

有人可以解释一下吗?

另外关于负载均衡器,一旦负载均衡器将请求转发给其后面的服务器之一,负载均衡器可以以某种方式将一些信息传递给它,这将有助于服务器直接响应原始客户端以避免延迟通过负载均衡器发回响应?

谢谢大家的帮助 . Thambi

3 回答

  • 0

    由于端口号为16位,因此在任何给定时间,单个Linux机器上最多只有65536个端口 .

    实际上是65535,因为你不能使用端口零 .

    当侦听套接字的服务器接受连接时,将分配端口号 .

    不,不是 . 传入连接使用与其连接的相同端口 . 在 accept() 上没有分配新端口 .

    因此,根据我的理解,在任何给定时间,给定计算机上最多只能存在65536个TCP / IP连接 .

    不,见上文 . 实际限制由内核和进程资源决定:打开FD,线程堆栈内存,内核缓冲区空间,......不是16位端口号 .

  • 0

    我的TCP连接由 (remote IP address, remote port, remote IP address, remote port) 元组唯一标识 .

    对于典型的服务器应用程序,只有一到三个本地IP地址和一个或两个本地端口 . 例如,Web服务器可能会侦听本地地址 ::1::ffff:93.184.216.342606:2800:220:1:248:1893:25c8:1946 (可能通过通配符地址,但这无关紧要),以及本地端口 80443 .

    对于单个本地地址和端口的简单情况,仍然是2128 16(少数用于特殊用途和广播地址),如果您希望以小于4百万个原子的单位与整个地球进行通信,这将是有问题的(如果你将地球上的所有物质转化为小病毒,那么也许是可能的 .

  • 0

    这个问题一直存在混淆,所以我将尝试用例子来解释它 .

    首先谈谈端口:每个人都知道它们不是物理上存在的,它们只是连接的额外标识信息,也是一种允许多个服务器监听同一地址的方法(如果没有端口的概念)一个服务器可能正在侦听一个地址,或者某个其他机制必须就位 . 端口也是 unsigned short ,因此它的值可以在0到65535(64k)之间 .

    现在,限制端口:它们在服务器端 bind ing:一个(服务器)套接字(让我们称之为SS)可以绑定到一个地址和端口:(除非在第一次绑定之前设置 SO_REUSEADDR ),只有一个套接字可以监听在一个特定的地址和端口,所以如果有人已经在端口上听你也听不到 . 有一些众所周知的端口(例如:sshd - 22 ,httpd - 80 ,RDP - 3389 ,...)在创建SS时应该避免,一般的guidline永远不会使用端口号<1k . 有关"reserved"端口的完整列表,请访问www.iana.org .

    link I posted in the comment中所述,有一个5项元组(2对1个附加元素),用于标识连接 (LocalIP: LocalPort, RemoteIP: RemotePort, Protocol) (最后一个成员只是为了严格,此时我们并不关心它) . 现在,对于侦听 IP:Port 的特定SS,对于连接到它的所有客户端(客户端套接字:CS),其中一对将是相同的,这取决于从以下位置查看连接的位置:

    • 服务器 endpoints :LocalIP:LocalPort

    • 客户 endpoints :RemoteIP:RemotePort(就像在镜子中一样) .

    现在我将在两台机器(Centos(192.168.149.43) - 服务器和Windows(192.168.137.10) - 客户端)上举例说明 . 我在Python中创建了一个虚拟TCP服务器(请注意,代码不是结构化的,没有异常处理,只支持IPv4,目的不是要有Python类,而是要查看一些套接字行为):

    import sys
    import select
    import socket
    
    HOST = "192.168.149.43"
    PORT = 4461
    WAIT_TIME = 0.5
    
    if __name__ == "__main__":
        conns = list()
        nconns = 0
        srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        srv.bind((HOST, PORT))
        srv.listen(0xFF)
        print "Entering loop, press a key to exit..."
        while sys.stdin not in select.select([sys.stdin], [], [], 0)[0]:
            if select.select([srv], [], [], WAIT_TIME)[0]:
                conn = srv.accept()
                print "Accepted connection from: (%s, %d)" % conn[1]
                conns.append(conn)
                nconns += 1
                print "Active connections:", nconns
        for item in conns:
            item[0].close()
        srv.close()
    print "Exiting."
    

    这是 netstat 输出服务器机器(在运行服务器应用程序之前) . 我选择端口4461进行通信:

    [cfati@xobved-itaf:~]> netstat -an | grep 4461
    [cfati@xobved-itaf:~]>
    

    所以与这个端口无关 . 现在启动服务器后(我必须修剪一些空格,以便输出适合这里):

    [cfati@xobved-itaf:~]> netstat -anp | grep 4461
    tcp      0    0 192.168.149.43:4461       0.0.0.0:*             LISTEN
    

    如您所见,有一个套接字侦听端口4461上的连接 .

    现在进入客户端计算机并启动Python解释器,在控制台中运行以下代码:

    >>> import sys
    >>> import socket
    >>> HOST = "192.168.149.43"
    >>> PORT = 4461
    >>>
    >>> def create(no=1):
    ...     ret = []
    ...     for i in xrange(no):
    ...         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ...         s.connect((HOST, PORT))
    ...         ret.append(s)
    ...     return ret
    ...
    >>> sockets=[]
    >>> sockets.extend(create())
    

    在服务器机器上输入最后一行之后,我们查看服务器输出:

    接受的连接来自:(192.168.137.10,64218)活动连接:1

    和相应的 netstat 输出:

    [cfati@xobved-itaf:~]> netstat -an | grep 4461
    tcp      0    0 192.168.149.43:4461       0.0.0.0:*             LISTEN
    tcp      0    0 192.168.149.43:4461       192.168.137.10:64218  ESTABLISHED
    

    您会看到 ESTABLISHED 连接(这是已接受的套接字 - AS):连接从端口64218上的192.168.137.10启动到端口4461上的192.168.149.43 .

    这是客户端计算机上相应的 netstat 输出(创建连接后):

    e:\Work\Dev>netstat -an | findstr 4461
     TCP    192.168.137.10:64218   192.168.149.43:4461    ESTABLISHED
    

    正如您所看到的那样,本地和远程(IP /端口)对(与服务器计算机上的输出相比)是相反的(就像我上面提到的关于镜像一样) . 如果我再次在解释器中的客户端计算机上再次运行最后一行(创建一个新连接):

    >>> sockets.extend(create())
    

    服务器应用程序的输出将显示另一个条目:

    接受的连接来自:(192.168.137.10,64268)活动连接:2

    而服务器机器上的 netstat 输出:

    [cfati@xobved-itaf:~]> netstat -an | grep 4461
    tcp      0    0 192.168.149.43:4461       0.0.0.0:*             LISTEN
    tcp      0    0 192.168.149.43:4461       192.168.137.10:64268  ESTABLISHED
    tcp      0    0 192.168.149.43:4461       192.168.137.10:64218  ESTABLISHED
    

    我不会发布 netstat 将在客户端计算机上输出的内容,因为它很明显 .

    现在,让我们看看每个对应于活动连接的2对:192.168.137.10: 64268 ,192.168.137.10: 64218 . 这两个端口由SS上调用的 accept 函数(UxWin)返回 .

    2个端口(64268和64218)由连接使用, but that doesn't mean that they cannot be used anymore . 其他套接字服务器可以监听它们(我在服务器机器上下文中讨论),或者它们可以作为来自其他地址的连接中使用的端口出现 . 这是一个假设的 netstat 输出:

    tcp      0    0 192.168.149.43:4461       192.168.137.45:64218  ESTABLISHED
    

    因此,端口64218也可以存在于192.168.137的连接中 . 45 (请注意,我更改了最后一个IP字节) .

    As a conclusion, you were somehow right :不能超过65535(不包括其他解决方案中指定的0)同时连接 from the same IP address . 这是一个巨大的数字,我不知道在现实世界中它是否可以满足,但即使如此,也有"tricks"来绕过它(一个例子是在2个不同的端口上监听2个SS,并配置客户端如果连接到服务器到一个端口无法使用另一个端口,那么来自同一地址的最大同时连接数可以增加一个因子,该数量等于我们有服务器监听的端口数) .

    负载 balancer 器处理来自多个地址的连接,因此它们的数量可以轻松增长到数十万个 .

相关问题