服务器是不是为每个客户端进程打开了套接字?

Posted

技术标签:

【中文标题】服务器是不是为每个客户端进程打开了套接字?【英文标题】:Has server opened socket for each client process?服务器是否为每个客户端进程打开了套接字? 【发布时间】:2013-09-06 17:53:13 【问题描述】:

我对套接字感到困惑。据我所知,套接字是 ip 地址和端口号的组合。它只是编程抽象,允许写入或读取流(在 TCP 的情况下)。现在我不确定的是,服务器在为客户端提供服务时是否有一个或多个套接字?假设http 位于端口 80。

来自不同客户端的所有数据是否都发送到一个套接字(服务器:80)并且某些 UBER 服务器进程根据传入地址区分它们,还是根据 TCP 层创建的客户端地址和端口号的组合来区分它们?有人可以用逐步算法(同时为多个客户端服务)彻底描述这一点,而不仅仅是服务器将套接字绑定到端口,服务器侦听套接字,服务器提供数据。

【问题讨论】:

您对什么操作系统感兴趣? 我的意思是一般。我不知道这因系统而异。但是,如果我必须专精于 Linux(android)和 Win,我想知道这一点。 【参考方案1】:

尽管我相信大多数操作系统/内核的运行方式类似,但我主要会与 Linux 交流。简短的回答是内核完成了大部分工作。

内核与某种网络接口进行通信,基本上只是将信号从线路传输到内核,反之亦然。套接字和地址仅仅是给定连接的描述符。内核跟踪哪些内部进程与哪些套接字/地址对相关,并将相应地引导数据。通常,这是作为 FIFO 实现的——先进先出。传入和传出数据都是如此。

如果服务器连接到多个客户端,通常由应用程序负责向每个连接的客户端发送单独的数据包,这意味着应用程序必须跟踪活动客户端的数量。一些内核和/或 NIC 可以为您完成其中的一些工作。如果这是一个本地网络,并且您想向连接到网络的每个客户端发送数据包,您可以发送广播数据包,该数据包只需发送一次,但每个连接都会收到。

如果您想了解更多信息,此链接非常详尽:

What is the difference between a port and a socket?

【讨论】:

【参考方案2】:

您将 TCP 连接与套接字混淆了。套接字不是网络级别的概念。是一个操作系统概念。 TCP 连接作为 (source-ip, source-port, dest-ip, dest-port) 的唯一组合存在于网络上。一个套接字是一个开放端口的句柄一个开放的连接(这个语句被稍微简化了)。当我开始时,我还认为这很令人困惑,并且是操作系统设计错误(但事实就是如此,我们被困住了)。设计错误是每个不同套接字的允许操作非常不同。这些用例应该是两个独立的概念,具有不同的名称和不同的 API。

正如您所见,套接字和连接之间没有 1:1 的关系。

有人可以用逐步算法彻底描述这一点

服务器打开一个套接字让操作系统知道它想要监听或连接。然后,每个接受的连接都会产生一个新的、独立的套接字。但是,每个新连接都在相同的服务器 IP 和服务器端口上。只是客户端 IP 和/或客户端端口不同。服务器读取和写入每个连接的套接字。开放端口套接字仅用于接受新连接。

服务器在概念上是这样的:

var openPortSocket = Open(80); //HTTP port
while(true) 
 var connectionSocket = openPortSocket.Accept();
 ServeConnectionOnNewThread(connectionSocket);

这是一个逻辑模型。实际的 API 调用是不同的。例如,大多数服务器使用异步 IO。不过,这与您的问题无关。

客户端必须为每个连接使用不同的客户端端口。这正是您的浏览器所做的。

【讨论】:

你能提供一些你在学习套接字和所有这些东西时使用的资源吗? @shotex 不幸的是,几乎所有网络上的套接字内容,包括官方文档,都在教导可怕的模式和彻底的错误!我不知道初学者如何不大量阅读和自己思考就可以了解套接字。【参考方案3】:

通常,在服务器端,在创建套接字并将其绑定到特定端口/地址组合后,将调用一个名为Listen(或类似)的函数。这使得这个绑定的套接字成为一个监听套接字——它只是在等待连接尝试开始。

在此之后,将在侦听套接字上调用类似Accept 的函数。此调用将从监听套接字接收一个挂起的连接请求,创建一个 new 套接字,然后返回它。

在连接期间,客户端和服务器之间的所有进一步通信都将通过这个新的套接字(在服务器端)。

如果服务器需要同时处理多个客户端连接,则可以使用不同的技术来实现可扩展性。一种简单的技术(扩展到数千个连接的客户端)是产生一个新的线程/进程(取决于你的操作系统上的便宜)来处理这个连接,然后是原始线程/process 返回调用Accept

其他技术可能涉及将套接字放置在某种形式的池中,或者能够让套接字生成由固定数量的线程处理的事件,当每个套接字都需要注意时。

【讨论】:

以上是关于服务器是不是为每个客户端进程打开了套接字?的主要内容,如果未能解决你的问题,请参考以下文章

通过分叉为每个子进程提供唯一 ID

使用套接字传输文件服务器/客户端 linux C

20145234黄斐《信息安全系统设计基础》第十三周学习总结

Linux 套接字与文件描述符

我可以使用非阻塞套接字使用“sendmsg/recvmsg”将 FD 从一个进程发送到另一个进程吗?

使用 gen_tcp 时的套接字接受率