多客户端如何同时连接到服务器上的一个端口(比如80)?

时间:2022-11-17 18:13:35

I understand the basics of how ports work. However, what I don't get is how multiple clients can simultaneously connect to say port 80. I know each client has a unique (for their machine) port. Does the server reply back from an available port to the client, and simply state the reply came from 80? How does this work?

我了解港口的基本工作原理。但是,我没有得到的是多个客户机如何同时连接到端口80。我知道每个客户端都有一个唯一的(机器)端口。服务器是否从可用端口返回到客户端,并简单地声明回复来自80?这是如何工作的呢?

5 个解决方案

#1


369  

First off, a "port" is just a number. All a "connection to a port" really represents is a packet which has that number specified in its "destination port" header field.

首先,“端口”只是一个数字。“连接到端口”实际上表示的是一个数据包,它的“目标端口”头字段中指定了这个数字。

Now, there are two answers to your question, one for stateful protocols and one for stateless protocols.

现在,有两个问题的答案,一个是有状态协议,一个是无状态协议。

For a stateless protocol (ie UDP), there is no problem because "connections" don't exist - multiple people can send packets to the same port, and their packets will arrive in whatever sequence. Nobody is ever in the "connected" state.

对于无状态协议(即UDP),没有问题,因为“连接”不存在——多个人可以将包发送到同一个端口,他们的包将以任何顺序到达。没有人处于“连接”状态。

For a stateful protocol (like TCP), a connection is identified by a 4-tuple consisting of source and destination ports and source and destination IP addresses. So, if two different machines connect to the same port on a third machine, there are two distinct connections because the source IPs differ. If the same machine (or two behind NAT or otherwise sharing the same IP address) connects twice to a single remote end, the connections are differentiated by source port (which is generally a random high-numbered port).

对于有状态协议(如TCP),连接由一个由源和目标端口、源和目标IP地址组成的4元组标识。因此,如果两个不同的机器连接到第三台机器上的同一个端口,由于源ip不同,因此有两个不同的连接。如果同一台机器(或NAT后面的两台或共享相同IP地址的两台)连接两次到一个远程端,那么连接将根据源端口(通常是一个随机的高编号端口)进行区分。

Simply, if I connect to the same web server twice from my client, the two connections will have different source ports from my perspective and destination ports from the web server's. So there is no ambiguity, even though both connections have the same source and destination IP addresses.

简单地说,如果我从客户机连接到同一个web服务器两次,那么从我的角度来看,这两个连接的源端口与web服务器的源端口不同。所以没有歧义,即使两个连接都有相同的源和目标IP地址。

Ports are a way to multiplex IP addresses so that different applications can listen on the same IP address/protocol pair. Unless an application defines its own higher-level protocol, there is no way to multiplex a port. If two connections using the same protocol have identical source and destination IPs and identical source and destination ports, they must be the same connection.

端口是一种多路复用IP地址的方法,以便不同的应用程序可以侦听相同的IP地址/协议对。除非应用程序定义了它自己的高级协议,否则无法将一个端口复用。如果使用相同协议的两个连接具有相同的源和目标ip以及相同的源和目标端口,那么它们必须是相同的连接。

#2


300  

Important:

重要的是:

I'm sorry to say that the response from "Borealid" is imprecise and somewhat incorrect - firstly there is no relation to statefulness or statelessness to answer this question, and most importantly the definition of the tuple for a socket is incorrect.

我很遗憾地说,“Borealid”的回答不准确,而且有些不正确——首先,这个问题与无状态或无状态没有关系,最重要的是套接字元的定义是错误的。

First remember below two rules:

首先要记住以下两条规则:

  1. Primary key of a socket: A socket is identified by {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL} not by {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT} - Protocol is an important part of a socket's definition.

    一个套接字的主键:由{SRC-IP、SRC-PORT、DEST-IP、DEST-PORT、PROTOCOL}而不是{SRC-IP、SRC-PORT、DEST-IP、DEST-PORT} -协议标识的套接字是套接字定义的一个重要部分。

  2. OS Process & Socket mapping: A process can be associated with (can open/can listen to) multiple sockets which might be obvious to many readers.

    OS过程&套接字映射:一个进程可以与(可以打开/可以侦听)多个套接字相关联,这对许多读者来说可能是显而易见的。

Example 1: Two clients connecting to same server port means: socket1 {SRC-A, 100, DEST-X,80, TCP} and socket2{SRC-B, 100, DEST-X,80, TCP}. This means host A connects to server X's port 80 and another host B also connects to same server X to the same port 80. Now, how the server handles these two sockets depends on if the server is single threaded or multiple threaded (I'll explain this later). What is important is that one server can listen to multiple sockets simultaneously.

示例1:连接到同一个服务器端口的两个客户机意味着:socket1 {SRC-A, 100, DEST-X,80, TCP}和socket2{SRC-B, 100, DEST-X,80, TCP}。这意味着主机A连接到服务器X的端口80,另一个主机B也连接到相同的服务器X连接到相同的端口80。现在,服务器如何处理这两个套接字取决于服务器是单线程的还是多线程的(稍后我将对此进行解释)。重要的是,一个服务器可以同时监听多个套接字。

To answer the original question of the post:

回答该职位的最初问题:

Irrespective of stateful or stateless protocols, two clients can connect to same server port because for each client we can assign a different socket (as client IP will definitely differ). Same client can also have two sockets connecting to same server port - since such sockets differ by SRC-PORT. With all fairness, "Borealid" essentially mentioned the same correct answer but the reference to state-less/full was kind of unnecessary/confusing.

不管有状态或无状态协议是什么,两个客户机都可以连接到相同的服务器端口,因为对于每个客户机,我们可以分配不同的套接字(因为客户机IP肯定不同)。同样的客户端也可以有两个套接字连接到相同的服务器端口——因为这些套接字与src端口不同。说句公道话,“Borealid”基本上说的是同样正确的答案,但是提到state less/full这个词就有点没必要了。

To answer the second part of the question on how a server knows which socket to answer. First understand that for a single server process that is listening to same port, there could be more than one sockets (may be from same client or from different clients). Now as long as a server knows which request is associated with which socket, it can always respond to appropriate client using the same socket. Thus a server never needs to open another port in its own node than the original one on which client initially tried to bind connect. If any server allocates different server-ports after a socket is bound, then in my opinion the server is wasting its resource and it must be needing the client to bind connect again to the new port assigned.

要回答关于服务器如何知道要回答哪个套接字的问题的第二部分。首先要明白,对于一个正在侦听相同端口的服务器进程,可能有多个套接字(可能来自相同的客户机或来自不同的客户机)。现在只要服务器知道哪个请求与哪个套接字相关联,它就可以使用相同的套接字对适当的客户端做出响应。因此,服务器永远不需要在自己的节点中打开另一个端口,而不需要打开客户机最初尝试绑定connect的原始节点。如果任何服务器在套接字被绑定后分配不同的服务器端口,那么在我看来,服务器正在浪费它的资源,它必须需要客户机再次绑定连接到分配的新端口。

A bit more for completeness:

更完整一点:

Example 2: It's very interesting question that can a server's two different processes listen to same port. If you do not consider protocol as one of parameter defining socket then the answer is no. Initiatively this is so because we can say that in such case for a single client trying to connect to a server-port will not have any mechanism to mention which of the two listening process the client intends to. This is the same theme asserted by rule (2). However this is WRONG answer because 'protocol' is also a part of the socket definition. Thus two processes in same node can listen to same port only if they are using different protocol. For example two unrelated clients (say one is using TCP and another is using UDP) can bind connect and communicate to the same server node and to the same port but they must be served by two different server-processes.

示例2:一个服务器的两个不同进程可以监听同一个端口,这是一个非常有趣的问题。如果您不认为协议是定义套接字的参数之一,那么答案是否定的。这样做的初衷是这样的,因为在这种情况下,对于试图连接服务器端口的单个客户机,将没有任何机制来说明客户机打算要连接的两个监听进程中的哪一个。这与规则(2)断言的主题相同,但是这是错误的答案,因为“protocol”也是套接字定义的一部分。因此,只有在使用不同的协议时,同一节点中的两个进程才能侦听相同的端口。例如,两个不相关的客户机(比如一个正在使用TCP,另一个正在使用UDP)可以绑定连接和通信到同一个服务器节点和同一个端口,但它们必须由两个不同的服务器进程提供服务。

Server Types - single & multiple:

服务器类型-单、多:

When a server's processes listening to a port that means multiple sockets can simultaneously connect and communicate with the same server-process. If a server uses only a single child-process to serve all the sockets then the server is called single-process/threaded and if the server uses many sub-processes to serve each socket by one sub-process then the server is called multi-process/threaded server. Note that irrespective of the server's type a server can/should always uses the same initial socket to respond back (no need to allocate another server-port).

当一个服务器的进程监听一个端口,这意味着多个套接字可以同时连接和通信相同的服务器进程。如果服务器只使用一个子进程来服务所有的套接字,那么服务器就称为单进程/线程,如果服务器使用多个子进程来服务每个套接字,那么服务器就称为多进程/线程服务器。注意,不管服务器的类型如何,服务器都可以/应该使用相同的初始套接字进行响应(不需要分配另一个服务器端口)。

Suggested Books and rest of the two volumes if you can.

如果可以的话,建议书和书的剩余部分。

A Note on Parent/Child Process (in response to query/comment of 'Ioan Alexandru Cucu')

关于父/子进程的说明(响应“Ioan Alexandru Cucu”的查询/注释)

Wherever I mentioned any concept in relation to two processes say A and B, consider that they are not related by parent child relationship. OS's (especially UNIX) by design allow a child process to inherit all File-descriptors (FD) from parents. Thus all the sockets (in UNIX like OS are also part of FD) that a process A listening to, can be listened by many more processes A1, A2, .. as long as they are related by parent-child relation to A. But an independent process B (i.e. having no parent-child relation to A) cannot listen to same socket. In addition, also note that this rule of disallowing two independent processes to listen to same socket lies on an OS (or its network libraries) and by far it's obeyed by most OS's. However, one can create own OS which can very well violate this restrictions.

当我提到任何与A和B这两个过程有关的概念时,请考虑它们与父子关系无关。OS(尤其是UNIX)允许子进程从父进程继承所有文件描述符(FD)。因此,一个进程所监听的所有套接字(在UNIX中,像OS也是FD的一部分)都可以被更多的进程A1、A2、……只要它们与A有父子关系,那么独立的进程B(即与A没有父子关系)就不能监听相同的套接字。此外,还要注意,不允许两个独立进程侦听相同套接字的规则位于操作系统(或其网络库)上,到目前为止,大多数操作系统都遵守这一规则。然而,我们可以创建自己的操作系统,它可以很好地违反这些限制。

#3


127  

TCP / HTTP Listening On Ports: How Can Many Users Share the Same Port

So, what happens when a server listen for incoming connections on a TCP port? For example, let's say you have a web-server on port 80. Let's assume that your computer has the public IP address of 24.14.181.229 and the person that tries to connect to you has IP address 10.1.2.3. This person can connect to you by opening a TCP socket to 24.14.181.229:80. Simple enough.

那么,当服务器监听TCP端口上的连接时,会发生什么情况呢?例如,假设您在端口80上有一个web服务器。假设您的计算机拥有24.14.181.229的公共IP地址,而试图连接您的人拥有10.1.2.3的IP地址。这个人可以通过打开TCP套接字来连接到24.14.181.229:80。很简单。

Intuitively (and wrongly), most people assume that it looks something like this:

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

    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.

This is intuitive, because from the standpoint of the client, he has an IP address, and connects to a server at IP:PORT. Since the client connects to port 80, then his port must be 80 too? This is a sensible thing to think, but actually not what happens. If that were to be correct, we could only serve one user per foreign IP address. Once a remote computer connects, then he would hog the port 80 to port 80 connection, and no one else could connect.

这是很直观的,因为从客户的角度来看,他有一个IP地址,并连接到IP:PORT的服务器。既然客户端连接到端口80,那么他的端口也必须是80 ?这是一个合理的想法,但实际上不是发生了什么。如果这是正确的,我们只能为每个外国IP地址提供一个用户。一旦一个远程计算机连接起来,他就会占用80端口到80端口连接,没有其他人可以连接。

Three things must be understood:

必须理解三件事:

1.) On a server, a process is listening on a port. Once it gets a connection, it hands it off to another thread. The communication never hogs the listening port.

1)。在服务器上,进程正在监听端口。一旦它得到一个连接,它就把它传递给另一个线程。交流从来不会占用听者的时间。

2.) Connections are uniquely identified by the OS by the following 5-tuple: (local-IP, local-port, remote-IP, remote-port, protocol). If any element in the tuple is different, then this is a completely independent connection.

2)。连接由OS通过以下5元组唯一标识:(本地ip、本地端口、远程ip、远程端口、协议)。如果tuple中的任何元素是不同的,那么这是一个完全独立的连接。

3.) When a client connects to a server, it picks a random, unused high-order source port. This way, a single client can have up to ~64k connections to the server for the same destination port.

3)。当客户机连接到服务器时,它选择一个随机的、未使用的高阶源端口。通过这种方式,单个客户机可以为相同的目标端口拥有到服务器的高达64k的连接。

So, this is really what gets created when a client connects to a server:

这就是当客户端连接到服务器时所创建的:

    Local Computer   | Remote Computer           | Role
    -----------------------------------------------------------
    0.0.0.0:80       | <none>                    | LISTENING
    127.0.0.1:80     | 10.1.2.3:<random_port>    | ESTABLISHED

Looking at What Actually Happens

First, let's use netstat to see what is happening on this computer. We will use port 500 instead of 80 (because a whole bunch of stuff is happening on port 80 as it is a common port, but functionally it does not make a difference).

首先,让我们使用netstat来查看这台计算机上发生了什么。我们将使用端口500而不是80(因为在端口80上发生了大量的事情,因为它是一个公共端口,但是在功能上它并没有什么不同)。

    netstat -atnp | grep -i ":500 "

As expected, the output is blank. Now let's start a web server:

如预期的那样,输出是空的。现在让我们启动一个web服务器:

    sudo python3 -m http.server 500

Now, here is the output of running netstat again:

下面是运行netstat的输出:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      - 

So now there is one process that is actively listening (State: LISTEN) on port 500. The local address is 0.0.0.0, which is code for "listening for all". An easy mistake to make is to listen on address 127.0.0.1, which will only accept connections from the current computer. So this is not a connection, this just means that a process requested to bind() to port IP, and that process is responsible for handling all connections to that port. This hints to the limitation that there can only be one process per computer listening on a port (there are ways to get around that using multiplexing, but this is a much more complicated topic). If a web-server is listening on port 80, it cannot share that port with other web-servers.

所以现在有一个进程正在积极地监听端口500 (State: LISTEN)。本地地址是0.0.0.0.0.0,这是“监听所有人”的代码。一个容易犯的错误是监听地址127.0.0.1,它只接受来自当前计算机的连接。这不是一个连接,这只是意味着一个进程请求绑定()到端口IP,这个进程负责处理到端口的所有连接。这暗示了在一个端口上每台计算机只能有一个进程的局限性(使用多路复用有很多方法可以解决这个问题,但是这是一个复杂得多的话题)。如果web服务器正在监听端口80,那么它不能与其他web服务器共享该端口。

So now, let's connect a user to our machine:

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

    quicknet -m tcp -t localhost:500 -p Test payload.

This is a simple script (https://github.com/grokit/dcore/tree/master/apps/quicknet) that opens a TCP socket, sends the payload ("Test payload." in this case), waits a few seconds and disconnects. Doing netstat again while this is happening displays the following:

这是一个简单的脚本(https://github.com/grokit/dcore/tree/master/apps/quicknet),它打开一个TCP套接字,发送有效负载(在本例中是“测试有效负载”),等待几秒钟,然后断开连接。在此期间再次执行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 -

If you connect with another client and do netstat again, you will see the following:

如果您再次连接另一个客户端并进行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:26813      ESTABLISHED -

... that is, the client used another random port for the connection. So there is never confusion between the IP addresses.

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

#4


24  

Normally, for every connecting client the server forks a child process that communicates with the client (TCP). The parent server hands off to the child process an established socket that communicates back to the client.

通常,对于每一个连接的客户端,服务器都与客户端(TCP)进行通信。父服务器将一个已建立的套接字交给子进程,该套接字与客户端通信。

When you send the data to a socket from your child server, the TCP stack in the OS creates a packet going back to the client and sets the "from port" to 80.

当您从子服务器将数据发送到套接字时,操作系统中的TCP堆栈创建一个回传给客户端的数据包,并将“从端口”设置为80。

#5


4  

Multiple clients can connect to the same port (say 80) on the server because on the server side, after creating a socket and binding (setting local IP and port) listen is called on the socket which tells the OS to accept incoming connections.

多个客户机可以连接到服务器上的同一个端口(比如80),因为在服务器端,在创建套接字并在套接字上调用绑定(设置本地IP和端口)侦听之后,套接字将告诉操作系统接受传入连接。

When a client tries to connect to server on port 80, the accept call is invoked on the server socket. This creates a new socket for the client trying to connect and similarly new sockets will be created for subsequent clients using same port 80.

当客户机试图连接到端口80上的服务器时,在服务器套接字上调用accept调用。这将为尝试连接的客户端创建一个新的套接字,并将为使用相同端口80的后续客户端创建类似的新套接字。

Words in italics are system calls.

斜体字是系统调用。

Ref

裁判

http://www.scs.stanford.edu/07wi-cs244b/refs/net2.pdf

http://www.scs.stanford.edu/07wi-cs244b/refs/net2.pdf

#1


369  

First off, a "port" is just a number. All a "connection to a port" really represents is a packet which has that number specified in its "destination port" header field.

首先,“端口”只是一个数字。“连接到端口”实际上表示的是一个数据包,它的“目标端口”头字段中指定了这个数字。

Now, there are two answers to your question, one for stateful protocols and one for stateless protocols.

现在,有两个问题的答案,一个是有状态协议,一个是无状态协议。

For a stateless protocol (ie UDP), there is no problem because "connections" don't exist - multiple people can send packets to the same port, and their packets will arrive in whatever sequence. Nobody is ever in the "connected" state.

对于无状态协议(即UDP),没有问题,因为“连接”不存在——多个人可以将包发送到同一个端口,他们的包将以任何顺序到达。没有人处于“连接”状态。

For a stateful protocol (like TCP), a connection is identified by a 4-tuple consisting of source and destination ports and source and destination IP addresses. So, if two different machines connect to the same port on a third machine, there are two distinct connections because the source IPs differ. If the same machine (or two behind NAT or otherwise sharing the same IP address) connects twice to a single remote end, the connections are differentiated by source port (which is generally a random high-numbered port).

对于有状态协议(如TCP),连接由一个由源和目标端口、源和目标IP地址组成的4元组标识。因此,如果两个不同的机器连接到第三台机器上的同一个端口,由于源ip不同,因此有两个不同的连接。如果同一台机器(或NAT后面的两台或共享相同IP地址的两台)连接两次到一个远程端,那么连接将根据源端口(通常是一个随机的高编号端口)进行区分。

Simply, if I connect to the same web server twice from my client, the two connections will have different source ports from my perspective and destination ports from the web server's. So there is no ambiguity, even though both connections have the same source and destination IP addresses.

简单地说,如果我从客户机连接到同一个web服务器两次,那么从我的角度来看,这两个连接的源端口与web服务器的源端口不同。所以没有歧义,即使两个连接都有相同的源和目标IP地址。

Ports are a way to multiplex IP addresses so that different applications can listen on the same IP address/protocol pair. Unless an application defines its own higher-level protocol, there is no way to multiplex a port. If two connections using the same protocol have identical source and destination IPs and identical source and destination ports, they must be the same connection.

端口是一种多路复用IP地址的方法,以便不同的应用程序可以侦听相同的IP地址/协议对。除非应用程序定义了它自己的高级协议,否则无法将一个端口复用。如果使用相同协议的两个连接具有相同的源和目标ip以及相同的源和目标端口,那么它们必须是相同的连接。

#2


300  

Important:

重要的是:

I'm sorry to say that the response from "Borealid" is imprecise and somewhat incorrect - firstly there is no relation to statefulness or statelessness to answer this question, and most importantly the definition of the tuple for a socket is incorrect.

我很遗憾地说,“Borealid”的回答不准确,而且有些不正确——首先,这个问题与无状态或无状态没有关系,最重要的是套接字元的定义是错误的。

First remember below two rules:

首先要记住以下两条规则:

  1. Primary key of a socket: A socket is identified by {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL} not by {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT} - Protocol is an important part of a socket's definition.

    一个套接字的主键:由{SRC-IP、SRC-PORT、DEST-IP、DEST-PORT、PROTOCOL}而不是{SRC-IP、SRC-PORT、DEST-IP、DEST-PORT} -协议标识的套接字是套接字定义的一个重要部分。

  2. OS Process & Socket mapping: A process can be associated with (can open/can listen to) multiple sockets which might be obvious to many readers.

    OS过程&套接字映射:一个进程可以与(可以打开/可以侦听)多个套接字相关联,这对许多读者来说可能是显而易见的。

Example 1: Two clients connecting to same server port means: socket1 {SRC-A, 100, DEST-X,80, TCP} and socket2{SRC-B, 100, DEST-X,80, TCP}. This means host A connects to server X's port 80 and another host B also connects to same server X to the same port 80. Now, how the server handles these two sockets depends on if the server is single threaded or multiple threaded (I'll explain this later). What is important is that one server can listen to multiple sockets simultaneously.

示例1:连接到同一个服务器端口的两个客户机意味着:socket1 {SRC-A, 100, DEST-X,80, TCP}和socket2{SRC-B, 100, DEST-X,80, TCP}。这意味着主机A连接到服务器X的端口80,另一个主机B也连接到相同的服务器X连接到相同的端口80。现在,服务器如何处理这两个套接字取决于服务器是单线程的还是多线程的(稍后我将对此进行解释)。重要的是,一个服务器可以同时监听多个套接字。

To answer the original question of the post:

回答该职位的最初问题:

Irrespective of stateful or stateless protocols, two clients can connect to same server port because for each client we can assign a different socket (as client IP will definitely differ). Same client can also have two sockets connecting to same server port - since such sockets differ by SRC-PORT. With all fairness, "Borealid" essentially mentioned the same correct answer but the reference to state-less/full was kind of unnecessary/confusing.

不管有状态或无状态协议是什么,两个客户机都可以连接到相同的服务器端口,因为对于每个客户机,我们可以分配不同的套接字(因为客户机IP肯定不同)。同样的客户端也可以有两个套接字连接到相同的服务器端口——因为这些套接字与src端口不同。说句公道话,“Borealid”基本上说的是同样正确的答案,但是提到state less/full这个词就有点没必要了。

To answer the second part of the question on how a server knows which socket to answer. First understand that for a single server process that is listening to same port, there could be more than one sockets (may be from same client or from different clients). Now as long as a server knows which request is associated with which socket, it can always respond to appropriate client using the same socket. Thus a server never needs to open another port in its own node than the original one on which client initially tried to bind connect. If any server allocates different server-ports after a socket is bound, then in my opinion the server is wasting its resource and it must be needing the client to bind connect again to the new port assigned.

要回答关于服务器如何知道要回答哪个套接字的问题的第二部分。首先要明白,对于一个正在侦听相同端口的服务器进程,可能有多个套接字(可能来自相同的客户机或来自不同的客户机)。现在只要服务器知道哪个请求与哪个套接字相关联,它就可以使用相同的套接字对适当的客户端做出响应。因此,服务器永远不需要在自己的节点中打开另一个端口,而不需要打开客户机最初尝试绑定connect的原始节点。如果任何服务器在套接字被绑定后分配不同的服务器端口,那么在我看来,服务器正在浪费它的资源,它必须需要客户机再次绑定连接到分配的新端口。

A bit more for completeness:

更完整一点:

Example 2: It's very interesting question that can a server's two different processes listen to same port. If you do not consider protocol as one of parameter defining socket then the answer is no. Initiatively this is so because we can say that in such case for a single client trying to connect to a server-port will not have any mechanism to mention which of the two listening process the client intends to. This is the same theme asserted by rule (2). However this is WRONG answer because 'protocol' is also a part of the socket definition. Thus two processes in same node can listen to same port only if they are using different protocol. For example two unrelated clients (say one is using TCP and another is using UDP) can bind connect and communicate to the same server node and to the same port but they must be served by two different server-processes.

示例2:一个服务器的两个不同进程可以监听同一个端口,这是一个非常有趣的问题。如果您不认为协议是定义套接字的参数之一,那么答案是否定的。这样做的初衷是这样的,因为在这种情况下,对于试图连接服务器端口的单个客户机,将没有任何机制来说明客户机打算要连接的两个监听进程中的哪一个。这与规则(2)断言的主题相同,但是这是错误的答案,因为“protocol”也是套接字定义的一部分。因此,只有在使用不同的协议时,同一节点中的两个进程才能侦听相同的端口。例如,两个不相关的客户机(比如一个正在使用TCP,另一个正在使用UDP)可以绑定连接和通信到同一个服务器节点和同一个端口,但它们必须由两个不同的服务器进程提供服务。

Server Types - single & multiple:

服务器类型-单、多:

When a server's processes listening to a port that means multiple sockets can simultaneously connect and communicate with the same server-process. If a server uses only a single child-process to serve all the sockets then the server is called single-process/threaded and if the server uses many sub-processes to serve each socket by one sub-process then the server is called multi-process/threaded server. Note that irrespective of the server's type a server can/should always uses the same initial socket to respond back (no need to allocate another server-port).

当一个服务器的进程监听一个端口,这意味着多个套接字可以同时连接和通信相同的服务器进程。如果服务器只使用一个子进程来服务所有的套接字,那么服务器就称为单进程/线程,如果服务器使用多个子进程来服务每个套接字,那么服务器就称为多进程/线程服务器。注意,不管服务器的类型如何,服务器都可以/应该使用相同的初始套接字进行响应(不需要分配另一个服务器端口)。

Suggested Books and rest of the two volumes if you can.

如果可以的话,建议书和书的剩余部分。

A Note on Parent/Child Process (in response to query/comment of 'Ioan Alexandru Cucu')

关于父/子进程的说明(响应“Ioan Alexandru Cucu”的查询/注释)

Wherever I mentioned any concept in relation to two processes say A and B, consider that they are not related by parent child relationship. OS's (especially UNIX) by design allow a child process to inherit all File-descriptors (FD) from parents. Thus all the sockets (in UNIX like OS are also part of FD) that a process A listening to, can be listened by many more processes A1, A2, .. as long as they are related by parent-child relation to A. But an independent process B (i.e. having no parent-child relation to A) cannot listen to same socket. In addition, also note that this rule of disallowing two independent processes to listen to same socket lies on an OS (or its network libraries) and by far it's obeyed by most OS's. However, one can create own OS which can very well violate this restrictions.

当我提到任何与A和B这两个过程有关的概念时,请考虑它们与父子关系无关。OS(尤其是UNIX)允许子进程从父进程继承所有文件描述符(FD)。因此,一个进程所监听的所有套接字(在UNIX中,像OS也是FD的一部分)都可以被更多的进程A1、A2、……只要它们与A有父子关系,那么独立的进程B(即与A没有父子关系)就不能监听相同的套接字。此外,还要注意,不允许两个独立进程侦听相同套接字的规则位于操作系统(或其网络库)上,到目前为止,大多数操作系统都遵守这一规则。然而,我们可以创建自己的操作系统,它可以很好地违反这些限制。

#3


127  

TCP / HTTP Listening On Ports: How Can Many Users Share the Same Port

So, what happens when a server listen for incoming connections on a TCP port? For example, let's say you have a web-server on port 80. Let's assume that your computer has the public IP address of 24.14.181.229 and the person that tries to connect to you has IP address 10.1.2.3. This person can connect to you by opening a TCP socket to 24.14.181.229:80. Simple enough.

那么,当服务器监听TCP端口上的连接时,会发生什么情况呢?例如,假设您在端口80上有一个web服务器。假设您的计算机拥有24.14.181.229的公共IP地址,而试图连接您的人拥有10.1.2.3的IP地址。这个人可以通过打开TCP套接字来连接到24.14.181.229:80。很简单。

Intuitively (and wrongly), most people assume that it looks something like this:

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

    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.

This is intuitive, because from the standpoint of the client, he has an IP address, and connects to a server at IP:PORT. Since the client connects to port 80, then his port must be 80 too? This is a sensible thing to think, but actually not what happens. If that were to be correct, we could only serve one user per foreign IP address. Once a remote computer connects, then he would hog the port 80 to port 80 connection, and no one else could connect.

这是很直观的,因为从客户的角度来看,他有一个IP地址,并连接到IP:PORT的服务器。既然客户端连接到端口80,那么他的端口也必须是80 ?这是一个合理的想法,但实际上不是发生了什么。如果这是正确的,我们只能为每个外国IP地址提供一个用户。一旦一个远程计算机连接起来,他就会占用80端口到80端口连接,没有其他人可以连接。

Three things must be understood:

必须理解三件事:

1.) On a server, a process is listening on a port. Once it gets a connection, it hands it off to another thread. The communication never hogs the listening port.

1)。在服务器上,进程正在监听端口。一旦它得到一个连接,它就把它传递给另一个线程。交流从来不会占用听者的时间。

2.) Connections are uniquely identified by the OS by the following 5-tuple: (local-IP, local-port, remote-IP, remote-port, protocol). If any element in the tuple is different, then this is a completely independent connection.

2)。连接由OS通过以下5元组唯一标识:(本地ip、本地端口、远程ip、远程端口、协议)。如果tuple中的任何元素是不同的,那么这是一个完全独立的连接。

3.) When a client connects to a server, it picks a random, unused high-order source port. This way, a single client can have up to ~64k connections to the server for the same destination port.

3)。当客户机连接到服务器时,它选择一个随机的、未使用的高阶源端口。通过这种方式,单个客户机可以为相同的目标端口拥有到服务器的高达64k的连接。

So, this is really what gets created when a client connects to a server:

这就是当客户端连接到服务器时所创建的:

    Local Computer   | Remote Computer           | Role
    -----------------------------------------------------------
    0.0.0.0:80       | <none>                    | LISTENING
    127.0.0.1:80     | 10.1.2.3:<random_port>    | ESTABLISHED

Looking at What Actually Happens

First, let's use netstat to see what is happening on this computer. We will use port 500 instead of 80 (because a whole bunch of stuff is happening on port 80 as it is a common port, but functionally it does not make a difference).

首先,让我们使用netstat来查看这台计算机上发生了什么。我们将使用端口500而不是80(因为在端口80上发生了大量的事情,因为它是一个公共端口,但是在功能上它并没有什么不同)。

    netstat -atnp | grep -i ":500 "

As expected, the output is blank. Now let's start a web server:

如预期的那样,输出是空的。现在让我们启动一个web服务器:

    sudo python3 -m http.server 500

Now, here is the output of running netstat again:

下面是运行netstat的输出:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      - 

So now there is one process that is actively listening (State: LISTEN) on port 500. The local address is 0.0.0.0, which is code for "listening for all". An easy mistake to make is to listen on address 127.0.0.1, which will only accept connections from the current computer. So this is not a connection, this just means that a process requested to bind() to port IP, and that process is responsible for handling all connections to that port. This hints to the limitation that there can only be one process per computer listening on a port (there are ways to get around that using multiplexing, but this is a much more complicated topic). If a web-server is listening on port 80, it cannot share that port with other web-servers.

所以现在有一个进程正在积极地监听端口500 (State: LISTEN)。本地地址是0.0.0.0.0.0,这是“监听所有人”的代码。一个容易犯的错误是监听地址127.0.0.1,它只接受来自当前计算机的连接。这不是一个连接,这只是意味着一个进程请求绑定()到端口IP,这个进程负责处理到端口的所有连接。这暗示了在一个端口上每台计算机只能有一个进程的局限性(使用多路复用有很多方法可以解决这个问题,但是这是一个复杂得多的话题)。如果web服务器正在监听端口80,那么它不能与其他web服务器共享该端口。

So now, let's connect a user to our machine:

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

    quicknet -m tcp -t localhost:500 -p Test payload.

This is a simple script (https://github.com/grokit/dcore/tree/master/apps/quicknet) that opens a TCP socket, sends the payload ("Test payload." in this case), waits a few seconds and disconnects. Doing netstat again while this is happening displays the following:

这是一个简单的脚本(https://github.com/grokit/dcore/tree/master/apps/quicknet),它打开一个TCP套接字,发送有效负载(在本例中是“测试有效负载”),等待几秒钟,然后断开连接。在此期间再次执行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 -

If you connect with another client and do netstat again, you will see the following:

如果您再次连接另一个客户端并进行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:26813      ESTABLISHED -

... that is, the client used another random port for the connection. So there is never confusion between the IP addresses.

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

#4


24  

Normally, for every connecting client the server forks a child process that communicates with the client (TCP). The parent server hands off to the child process an established socket that communicates back to the client.

通常,对于每一个连接的客户端,服务器都与客户端(TCP)进行通信。父服务器将一个已建立的套接字交给子进程,该套接字与客户端通信。

When you send the data to a socket from your child server, the TCP stack in the OS creates a packet going back to the client and sets the "from port" to 80.

当您从子服务器将数据发送到套接字时,操作系统中的TCP堆栈创建一个回传给客户端的数据包,并将“从端口”设置为80。

#5


4  

Multiple clients can connect to the same port (say 80) on the server because on the server side, after creating a socket and binding (setting local IP and port) listen is called on the socket which tells the OS to accept incoming connections.

多个客户机可以连接到服务器上的同一个端口(比如80),因为在服务器端,在创建套接字并在套接字上调用绑定(设置本地IP和端口)侦听之后,套接字将告诉操作系统接受传入连接。

When a client tries to connect to server on port 80, the accept call is invoked on the server socket. This creates a new socket for the client trying to connect and similarly new sockets will be created for subsequent clients using same port 80.

当客户机试图连接到端口80上的服务器时,在服务器套接字上调用accept调用。这将为尝试连接的客户端创建一个新的套接字,并将为使用相同端口80的后续客户端创建类似的新套接字。

Words in italics are system calls.

斜体字是系统调用。

Ref

裁判

http://www.scs.stanford.edu/07wi-cs244b/refs/net2.pdf

http://www.scs.stanford.edu/07wi-cs244b/refs/net2.pdf