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

发布于 2024-09-11 20:03:54 字数 114 浏览 7 评论 0原文

我了解端口工作原理的基础知识。但是,我不明白的是多个客户端如何同时连接到端口 80。我知道每个客户端都有一个唯一的(对于他们的机器)端口。服务器是否从可用端口回复客户端,并简单地声明回复来自 80?这是如何运作的?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

耀眼的星火 2024-09-18 20:03:54

首先,“端口”只是一个数字。所有“到端口的连接”真正代表的是一个数据包,该数据包的“目标端口”标头字段中指定了该编号。

现在,您的问题有两个答案,一种用于有状态协议,一种用于无状态协议。

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

对于有状态协议(如 TCP),连接由由源端口和目标端口以及源 IP 地址和目标 IP 地址组成的 4 元组标识。因此,如果两台不同的计算机连接到第三台计算机上的同一端口,则会出现两个不同的连接,因为源 IP 不同。如果同一台计算机(或两台位于 NAT 后面或共享相同 IP 地址的计算机)两次连接到单个远程端,则连接将按源端口(通常是随机的高编号端口)进行区分。

简单地说,如果我从客户端两次连接到同一个 Web 服务器,则从我的角度来看,这两个连接将具有不同的源端口,而从 Web 服务器的角度来看,这两个连接将具有不同的源端口和目标端口。因此,即使两个连接具有相同的源 IP 地址和目标 IP 地址,也不存在歧义。

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

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.

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).

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.

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 simultaneously have identical source and destination IPs and identical source and destination ports, they must be the same connection.

优雅的叶子 2024-09-18 20:03:54

重要提示:

我很遗憾地说,“Borealid”的回答不精确并且有些不正确 - 首先,回答这个问题与有状态或无状态无关,最重要的是元组的定义对于套接字是不正确的。

首先记住以下两条规则:

  1. 套接字的主键:套接字由 {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}< 标识/code> 不是 {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT} - 协议是套接字定义的重要部分。


  2. 操作系统进程和套接字映射:一个进程可以与多个套接字关联(可以打开/可以侦听),这对许多读者来说可能是显而易见的。

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

回答帖子的原始问题:

无论是有状态还是无状态协议,两个客户端都可以连接到同一个服务器端口,因为对于每个客户端,我们可以分配不同的套接字(因为客户端 IP 肯定会不同) )。同一客户端还可以有两个套接字连接到同一服务器端口 - 因为这些套接字的 SRC-PORT 有所不同。平心而论,“Borealid”本质上提到了相同的正确答案,但对无状态/完整的引用有点不必要/令人困惑。

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

为了完整起见,请多说一点:

示例 2: 这是一个非常有趣的问题:“服务器上的两个不同进程能否侦听同一端口”。如果您不认为协议是定义套接字的参数之一,那么答案是否定的。之所以如此,是因为我们可以说,在这种情况下,尝试连接到服务器端口的单个客户端将没有任何机制来提及客户端打算连接到两个侦听进程中的哪一个。这与规则 (2) 所主张的主题相同。然而,这是错误的答案,因为“协议”也是套接字定义的一部分。因此,同一节点中的两个进程只有使用不同的协议才能侦听同一端口。例如,两个不相关的客户端(假设一个使用 TCP,另一个使用 UDP)可以连接到同一服务器节点和同一端口并进行通信,但它们必须由两个不同的服务器进程提供服务。

服务器类型 - 单服务器和单服务器多个:

当一个服务器进程监听一个端口时,意味着多个套接字可以同时与同一个服务器进程连接和通信。如果服务器仅使用单个子进程来服务所有套接字,则该服务器称为单进程/线程服务器;如果服务器使用多个子进程通过一个子进程为每个套接字提供服务,则该服务器称为多线程进程/线程服务器。请注意,无论服务器的类型如何,服务器都可以/应该始终使用相同的初始套接字来响应(无需分配另一个服务器端口)。

如果可以的话,推荐书籍以及两卷的其余部分。

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

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

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.

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.

  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.

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 the 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.

To answer the original question of the post:

Irrespective of stateful or stateless protocols, two clients can connect to the same server port because for each client we can assign a different socket (as the client IP will definitely differ). The same client can also have two sockets connecting to the 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.

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 the same port, there could be more than one socket (maybe from the 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 the 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 the client initially tried to 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 connect again to the new port assigned.

A bit more for completeness:

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

Server Types - single & multiple:

When a server 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 a multi-process/threaded server. Note that irrespective of the server's type a server can/should always use the same initial socket to respond back (no need to allocate another server port).

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

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

Wherever I mentioned any concept in relation to two processes say A and B, consider that they are not related by the parent-child relationship. OS's (especially UNIX) by design allows 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 process A listening to can be listened to 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 the same socket. In addition, also note that this rule of disallowing two independent processes to listen to the 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 restriction.

静赏你的温柔 2024-09-18 20:03:54

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.

这是直觉的,因为从客户端的角度来看,他有一个 IP 地址,并连接到位于 IP:PORT 的服务器。既然客户端连接的是80端口,那么他的端口也一定是80吧?这是一个合理的想法,但实际上却并非如此。如果这是正确的,我们只能为每个外部 IP 地址一名用户提供服务。一旦远程计算机连接,他就会霸占80端口到80端口的连接,其他人就无法连接。

必须了解三件事:

1.) 在服务器上,进程正在侦听端口。一旦获得连接,它就会将其交给另一个线程。通信永远不会占用监听端口。

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

3.) 当客户端连接到服务器时,它会选择一个随机的、未使用的高阶源端口。这样,单个客户端可以通过相同的目标端口与服务器建立多达约 64k 的连接。

因此,这实际上是客户端连接到服务器时创建的内容:

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

首先查看实际发生的情况

,让我们使用 netstat 来查看该计算机上发生的情况。我们将使用端口 500 而不是 80(因为端口 80 上发生了很多事情,因为它是一个公共端口,但从功能上来说它没有什么区别)。

    netstat -atnp | grep -i ":500 "

正如预期的那样,输出为空白。现在让我们启动一个 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 上主动侦听(状态:LISTEN)。本地地址是 0.0.0.0,它是“的代码”为所有人倾听”。一个容易犯的错误是监听地址 127.0.0.1,该地址只接受来自当前计算机的连接。所以这不是一个连接,这只是意味着一个进程请求bind()到端口IP,并且该进程负责处理到该端口的所有连接。这暗示了一个限制,即每台计算机只能有一个进程在端口上侦听(有多种方法可以使用多路复用来解决此问题,但这是一个更加复杂的主题)。如果 Web 服务器正在侦听端口 80,则它无法与其他 Web 服务器共享该端口。

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

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

这是一个简单的脚本 (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 -

如果您与另一个客户端连接并再次执行 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 -

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

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.

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.

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.

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.

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.

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 -atnp | grep -i ":500 "

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

    sudo python3 -m http.server 500

Now, here is the output of running netstat again:

    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.

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:

    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:

    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.

白芷 2024-09-18 20:03:54

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

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

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.

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.

愛放△進行李 2024-09-18 20:03:54

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

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

斜体字是系统调用。

参考

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

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.

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.

Words in italics are system calls.

Ref

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文