我有一个关于实现负载均衡器或执行TCP / IP的TCP / IP服务器程序的具体问题。
由于端口号为16位,因此在任何给定时间,单个Linux机器上最多只有65536个端口。 TCP / IP需要一个端口号与外界通信。 1)当客户端建立连接时,选择短暂的端口号。 2)当监听套接字的服务器接受连接时,分配端口号。
因此,根据我的理解,在任何给定时间,给定计算机上最多只能存在65536个TCP / IP连接。
那么一些或大多数负载均衡器如何声称200,000或更多并发连接呢?
有人可以解释一下吗?
同样关于负载均衡器,一旦负载均衡器将请求转发给其后面的服务器之一,负载均衡器就能以某种方式将一些信息传递给它,这将有助于服务器直接响应原始客户端以避免通过负载均衡器发回响应的延迟?
感谢大家的帮助。 Thambi
答案 0 :(得分:0)
实际上由于端口号为16位,因此在任何给定时间,单个Linux机器上最多只有65536个端口。
65535,因为你不能使用端口零。
当侦听套接字的服务器接受连接时,会分配端口号。
不,不是。传入连接使用与其连接的相同端口。 accept()
上没有分配新端口。
因此,根据我的理解,在任何给定时间,给定计算机上最多只能存在65536个TCP / IP连接。
不,见上文。实际限制由内核和进程资源决定:打开FD,线程堆栈内存,内核缓冲区空间,......不是16位端口号。
答案 1 :(得分:0)
我的TCP连接由(remote IP address, remote port, remote IP address, remote port)
元组唯一标识。
对于典型的服务器应用程序,只有一到三个本地IP地址和一个或两个本地端口。例如,Web服务器可能会侦听本地地址::1
,::ffff:93.184.216.34
和2606:2800:220:1:248:1893:25c8:1946
(可能通过通配符地址,但这不相关)和本地端口{{1 }和80
。
对于单个本地地址和端口的简单情况,仍然是2 128 + 16 (少数用于特殊用途和广播地址),如果您愿意,这将是有问题的以不到4百万个原子为单位与整个地球进行通信(如果将地球上的所有物质转化为小病毒,可能可能)。
答案 2 :(得分:0)
这个问题之间存在混淆,所以我试着用例子来解释它。
首先谈谈端口:每个人都知道它们不是物理上存在的,它们只是连接的额外标识信息,也是允许多个服务器监听同一地址的一种方式(如果有的话)没有端口的概念只有一个服务器可以监听一个地址,或者必须有一些其他机制。)此外,端口为unsigned short
,因此它可以包含 0 和 65535 (64k)之间的值。
现在,关于端口的限制:当bind
时,它们位于服务器端:(服务器)套接字(让它称之为SS)可以绑定到地址和端口:(除非{{ 1}}在第一次绑定之前设置,)一次只有一个套接字可以监听特定的地址和端口,所以如果有人已经在端口上监听,你也无法收听。有一些众所周知的端口(例如: sshd - 22 , httpd - 80 , RDP < / em> - 3389 ,...)创建时应避免使用
SS,一般指南永远不会使用端口号&lt; 1K。有关&#34;保留&#34;的完整列表港口,请访问www.iana.org。
如link I posted in the comment中所述,标识连接的5项元组(2对+ 1个附加元素)(LocalIP:LocalPort,RemoteIP:RemotePort,Protocol) (最后一个成员只是为了严厉,此时我们并不关心它)。现在,对于侦听 IP:端口的特定SS,对于连接到它的所有客户端(客户端套接字:CS),其中一对将是相同的,这取决于从哪里查看连接:
现在我将在两台机器( Centos (192.168.149.43) - 服务器和 Windows (192.168.137.10) - 客户端)上举例说明。我在 Python 中创建了一个虚拟TCP服务器(请注意,代码不是结构化的,没有异常处理,只有 IPv4 能力,目的不是拥有 Python 类,但要查看一些套接字行为):
SO_REUSEADDR
这是服务器计算机上的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."
输出(在运行服务器应用程序之前)。我选择了端口4461进行通信:
netstat
所以与此端口无关。现在启动服务器后(我必须修剪一些空格,以便输出适合这里):
[cfati@xobved-itaf:~]> netstat -an | grep 4461
[cfati@xobved-itaf:~]>
如您所见,有一个套接字侦听端口4461上的连接。
现在进入客户端计算机并启动 Python 解释器,在控制台中运行以下代码:
[cfati@xobved-itaf:~]> netstat -anp | grep 4461
tcp 0 0 192.168.149.43:4461 0.0.0.0:* LISTEN
在服务器机器上输入最后一行之后,我们查看服务器输出:
接受的连接来自:(192.168.137.10,64218)
有效连接:1
相应的>>> 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())
输出:
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
连接(这是接受的套接字 - AS):连接是从端口 64218 上的 192.168.137.10 启动到<端口 4461 上的em> 192.168.149.43 。
这里是客户端计算机上相应的ESTABLISHED
输出(创建连接后):
netstat
正如您所看到的那样,本地和远程(IP /端口)对(与服务器计算机上的输出相比)是相反的(就像我上面提到的关于镜像一样)。如果我再次在解释器中的客户端计算机上再次运行最后一行(创建一个新连接):
e:\Work\Dev>netstat -an | findstr 4461
TCP 192.168.137.10:64218 192.168.149.43:4461 ESTABLISHED
服务器应用程序的输出将显示另一个条目:
接受的连接来自:(192.168.137.10,64268)
有效连接:2
在服务器计算机上输出>>> sockets.extend(create())
时:
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
将在客户端计算机上输出的内容,因为它很明显。
现在,让我们看看每个对应于有效连接的2对: 192.168.137.10 : 64268 , 192.168.137.10 :<强> 64218 即可。这两个端口由SS上调用的netstat
函数(Ux或Win)返回。
2个端口(64268和64218)由连接使用,但这并不意味着它们不能再使用。其他套接字服务器可以监听它们(我在服务器机器上下文中讨论),或者它们可以作为来自其他地址的连接中使用的端口出现。这是一个假设的accept
输出:
netstat
因此,端口64218也可以出现在 192.168.137。 45 的连接中(注意我更改了最后一个IP字节)。
作为结论,您显然是正确的:不能超过65535(不包括其他解决方案中指定的0)来自同一IP地址的同时连接 / strong>即可。这是一个巨大的数字,我不知道在现实世界中是否可以满足,但即使如此,也有&#34;技巧&#34;绕过它(一个例子是有2个以上的SS在2个以上的不同端口上侦听,并配置客户端,如果连接到服务器到一个端口无法使用另一个端口,那么来自同一地址的最大同时连接数可以增加通过等于我们有服务器监听的端口数的因子。)
负载均衡器处理来自多个地址的连接,因此它们的数量可以轻松增长到数十万个。