Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets TCP:两个不同的套接字可以共享一个端口吗?_Sockets_Tcp_Network Programming_Port - Fatal编程技术网

Sockets TCP:两个不同的套接字可以共享一个端口吗?

Sockets TCP:两个不同的套接字可以共享一个端口吗?,sockets,tcp,network-programming,port,Sockets,Tcp,Network Programming,Port,这可能是一个非常基本的问题,但它让我感到困惑 两个不同连接的插座能否共享一个端口?我正在编写一个应用服务器,它应该能够处理超过100k的并发连接,我们知道系统上可用的端口数大约为60k(16位)。连接的套接字被分配给一个新的(专用)端口,因此这意味着并发连接的数量受端口数量的限制,除非多个套接字可以共享同一端口。所以问题来了 已连接的套接字被分配给新的(专用)端口 这是一种常见的直觉,但它是不正确的。未将连接的套接字分配给新的/专用端口。TCP堆栈必须满足的唯一实际约束是(本地\地址、本地\端口

这可能是一个非常基本的问题,但它让我感到困惑

两个不同连接的插座能否共享一个端口?我正在编写一个应用服务器,它应该能够处理超过100k的并发连接,我们知道系统上可用的端口数大约为60k(16位)。连接的套接字被分配给一个新的(专用)端口,因此这意味着并发连接的数量受端口数量的限制,除非多个套接字可以共享同一端口。所以问题来了

已连接的套接字被分配给新的(专用)端口

这是一种常见的直觉,但它是不正确的。未将连接的套接字分配给新的/专用端口。TCP堆栈必须满足的唯一实际约束是(本地\地址、本地\端口、远程\地址、远程\端口)的元组对于每个套接字连接都必须是唯一的。因此,只要端口上的每个套接字连接到不同的远程位置,服务器就可以有多个使用相同本地端口的TCP套接字


请参阅下面的“套接字对”段落:

A服务器套接字侦听单个端口。该服务器上所有已建立的客户端连接都与连接服务器端的同一侦听端口相关联。已建立的连接通过客户端和服务器端IP/端口对的组合进行唯一标识。同一服务器上的多个连接可以共享相同的服务器端IP/端口对,只要它们与不同的客户端IP/端口对相关联,并且服务器能够处理可用系统资源允许的尽可能多的客户端


客户端上,新出站连接通常使用随机的客户端端口,在这种情况下,如果您在短时间内建立了大量连接,则可能会耗尽可用端口。

理论上,是的。练习,而不是练习。大多数内核(包括linux)不允许对已分配的端口进行第二次
bind()
。这不是一个真正的大补丁,使这允许

从概念上讲,我们应该区分套接字和端口。套接字是双向通信端点,即我们可以发送和接收字节的“东西”。这是一个概念性的东西,在名为“socket”的包头中没有这样的字段

端口是能够识别套接字的标识符。对于TCP,端口是16位整数,但也有其他协议(例如,在unix套接字上,“端口”本质上是字符串)

主要问题如下:如果传入数据包到达,内核可以通过其目标端口号识别其套接字。这是最常见的方式,但不是唯一的可能性:

  • 套接字可以通过传入数据包的目标IP来识别。例如,如果一台服务器同时使用两个IP,情况就是这样。例如,我们可以在相同的端口上运行不同的Web服务器,但在不同的IP上运行
  • 套接字也可以通过其源端口和ip来识别。在许多负载平衡配置中都是这样
因为您在应用服务器上工作,所以它将能够做到这一点。

TCP/HTTP侦听端口:有多少用户可以共享同一端口 那么,当服务器侦听TCP端口上的传入连接时会发生什么情况?例如,假设您在端口80上有一个web服务器。假设您的计算机的公共IP地址为24.14.181.229,尝试与您连接的人的IP地址为10.1.2.3。此人可以通过打开24.14.181.229:80的TCP套接字与您连接。很简单

直觉上(也是错误的),大多数人认为它看起来像这样:

    Local Computer    | Remote Computer
    --------------------------------
    <local_ip>:80     | <foreign_ip>:80

    ^^ not actually what happens, but this is the conceptual model a lot of people have in mind.
正如预期的那样,输出为空。现在,让我们启动一个web服务器:

    sudo python3 -m http.server 500
现在,这里是再次运行netstat的输出:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      - 
因此,现在有一个进程正在端口500上积极侦听(State:LISTEN)。本地地址是0.0.0.0,这是“侦听所有ip地址”的代码。一个容易犯的错误是只监听端口127.0.0.1,它只接受来自当前计算机的连接。所以这不是一个连接,这只是意味着一个进程请求将()绑定到端口IP,该进程负责处理到该端口的所有连接。这暗示了一个限制,即每台计算机只能有一个进程监听一个端口(使用多路复用可以绕过这个限制,但这是一个复杂得多的主题)。如果web服务器正在侦听端口80,则无法与其他web服务器共享该端口

现在,让我们将用户连接到我们的机器:

    quicknet -m tcp -t localhost:500 -p Test payload.
这是一个简单的脚本(),它打开一个TCP套接字,发送有效负载(“Test payload.”,在本例中为“Test payload”),等待几秒钟并断开连接。在此过程中再次执行netstat将显示以下内容:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:54240      ESTABLISHED -
    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:26813      ESTABLISHED -
如果您连接到另一个客户端并再次执行netstat,您将看到以下内容:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:54240      ESTABLISHED -
    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:26813      ESTABLISHED -

。。。也就是说,客户端使用另一个随机端口进行连接。因此,IP地址之间永远不会混淆。

不。不可能在特定时刻共享同一端口。但是,您可以使应用程序在不同的时刻进行端口访问

我想没有一个答案能告诉我们这个过程的每一个细节,所以这里是:

考虑一个HTTP服务器:

  • 它要求操作系统将端口80绑定到一个或多个IP地址(如果选择127.0.0.1,则只接受本地连接。您可以选择0.0.0.0绑定到所有IP地址(本地主机、本地网络、广域网、两个IP版本))

  • 当客户端连接到该端口时,它会将其锁定一段时间(这就是套接字有积压工作的原因:它将大量连接尝试排入队列)