【问题标题】:What things are exactly happening when server socket accept client sockets?当服务器套接字接受客户端套接字时,究竟发生了什么?
【发布时间】:2015-03-29 16:48:54
【问题描述】:

我正在学习套接字编程,而服务器套接字accept() 让我感到困惑。我为服务器套接字accept()写了两个场景,请看:

  1. 当服务器套接字执行accept() 时,它会创建一个新的(客户端)套接字,该套接字绑定到与服务器套接字绑定的端口不同的端口。所以套接字通信是通过新绑定的端口完成的,服务器套接字(仅限accept())正在原来绑定的端口上等待另一个客户端连接。

我认为这不太正确,因为 (1) 端口与单个进程匹配,并且 (2) 套接字接受是进程内部的问题,并且单个进程可以有多个套接字。所以想到了第二种情况,基于一些stackoverflow的答案:

  1. 当服务器套接字执行accept() 时,它会创建一个绑定到任何特定端口的新(客户端)套接字。当客户端与服务器通信时,它使用绑定到服务器套接字的端口(谁accept()s 连接)和哪个客户端套接字实际通信被解析(sourceIP, sourcePort, destIP, destPort) tuple from TCP header(?) at Transmission level(这也很可疑,因为我认为套接字在某种程度上是一个应用程序级对象)

这种情况也引发了一些问题。如果套接字通信仍然使用服务器套接字的端口,即客户端向服务器套接字端口发送一些消息,它不使用服务器套接字的积压队列吗?我的意思是,如何区分来自客户端的消息connect()read() or write()?以及如何在没有任何端口绑定的情况下将它们解析到服务器中的每个客户端套接字?

如果我的其中一个场景是正确的,那会回答以下问题吗?或者,我的两种情况都是错误的。如果您能指导我正确答案,或者至少是对一些相关文本进行学习,我将不胜感激。

【问题讨论】:

  • This 是我搜索的问题之一,它对场景2 投了赞成票:
  • 不,它没有。没有关于创建未绑定到任何端口的套接字的内容。它不支持您的任何一种方案。
  • accept 调用非常简单。如果成功,它会创建一个新套接字,该套接字引用到内核已经接受的其中一个侦听套接字的连接。它只是绑定到那个特定的 TCP 连接。该特定 TCP 连接由源 IP 地址、源端口、目标 IP 地址和目标端口的唯一组合标识。

标签: sockets tcp


【解决方案1】:

当您创建一个套接字并对该套接字进行绑定然后进行侦听时,您所拥有的就是所谓的listening socket。 建立连接后,这个套接字基本上被克隆到一个新的套接字,这个套接字被称为the servicing socket,它绑定的端口仍然与原始端口相同。

但是这个套接字和之前的监听套接字有一个重要的区别。即它是socket pair 的一部分。 唯一标识连接的是套接字对。所以图片中有2个socket对应一个socket pair,那么TCP通信通道的两端就有2个IP地址和2个端口。在克隆服务套接字期间,TCP 内核将分配所谓的TCB,并在其中存储这 2 个 IP@ 和 2 个端口。 TCB 还包含属于 TCB 的套接字号。

每次进入 TCP 段时,都会检查 TCP 标头是否为 SYN,对于 SYN,您将建立连接,以便您已经通过,但随后内核正在检查其侦听列表插座。如果是普通的 TCP 数据包,而不是 SYN,则两个端口号都在 TCP 标头中,而 IP@ 是 IP 标头的一部分,因此使用此信息,内核能够找到属于该 TCP 连接的 TCP。 (对于一个 SYN,这个信息也在那里,但正如我所说,对于一个 SYN 你必须只处理监听套接字)

简而言之就是它的工作原理。

此信息可在 UNIX 网络编程:套接字网络 API 中找到。在那里描述了到套接字的链接,而在其他参考资料中通常没有详细描述,而是通常突出显示 TCP 的细节。

【讨论】:

  • 不要对非代码文本使用代码格式。
  • 我使用反引号转义 like _so_ 来突出定义,是的书名,这是错的吗?
  • 是的,这是错误的。那是为了代码。格式化书籍引文的习惯方法是使用斜体。
【解决方案2】:

当服务器套接字执行accept() 时,它会创建一个新的(客户端)套接字,该套接字绑定到与服务器套接字绑定的端口不同的端口。所以套接字通信是通过新绑定的端口完成的,服务器套接字(仅用于accept())正在等待原始绑定端口上的另一个客户端连接。

没有。

我认为这不是很正确的答案

这是一个错误的答案。

因为 (1) 端口匹配单个进程

这并不意味着任何相关的事情。

和 (2) 套接字接受是进程内的问题

也不是。实际上,它似乎根本没有任何意义。

单个进程可以有多个套接字。

确实如此,但这与您的答案错误的原因没有任何关系。您的答案错误的原因是没有使用第二个端口。

当服务器套接字执行accept()时,它会创建一个新的(客户端)套接字,该套接字未绑定到任何特定端口

没有。它创建了第二个套接字,它继承了服务器套接字的所有内容:端口号、缓冲区大小、套接字选项……除了文件描述符和 LISTENING 状态之外的所有内容,也许我忘记了其他内容。然后它将套接字的远程 IP:port 设置为客户端的端口,并将套接字置于 ESTABLISHED 状态。

当客户端与服务器通信时

客户端已经与服务器通信。这就是我们创建这个套接字的原因。

它使用绑定到服务器套接字的端口(谁接受()的连接),实际通信的客户端套接字由传输级别的 TCP 标头(?)中的 (sourceIP, sourcePort, destIP, destPort) 元组解析

这已经发生了。

这也很可疑,因为我认为套接字在某种程度上是应用程序级对象)

不,不是。套接字是内核级对象,具有应用级文件描述符来标识它。

如果socket通信仍然使用服务器socket的端口,即客户端向服务器socket端口发送一些消息,它不使用服务器socket的积压队列吗?

没有。积压队列用于传入的连接请求,而不是用于数据。传入的数据进入套接字接收缓冲区。

我的意思是,如何区分来自客户端的消息 connect() 和 read() 或 write()?

因为connect() 请求在 TCP 标头中设置了特殊位。最后一部分可以和数据结合起来。

在没有任何端口绑定的情况下,如何将它们解析到服务器中的每个客户端套接字?

端口绑定发生在对accept() 的调用中创建套接字的那一刻。你自己发明了这个困难。这不是真的。

如果我的一个场景是正确的,会回答以下问题吗?

它们都不正确。

或者我可能在做两个错误的场景,所以非常感谢您提供正确的答案,或者至少提供一些相关的文本来学习。

您肯定已经有相关的文本要学习了吗?如果您不这样做,您应该阅读RFC 793 或 W.R. Stevens,TCP/IP Illustrated,第一卷,相关章节。你在这里有几个主要的误解。

【讨论】:

  • sockets 没有绑定仅仅通过创建它们。您要么绑定,然后当然绑定,要么进行主动连接。在主动连接期间,如果套接字未绑定,则分配一个临时端口,不会很快,至少我维护的 TCP/IP 堆栈是这样的。
  • @PhilipStuyck 这里完全混乱。内核创建的套接字可以随时绑定。您所描述的是 applicationclient 套接字的作用。问题是关于 kernelaccept(). 创建的套接字做了什么我不知道“如果套接字未绑定,则在主动接受期间”甚至意味着什么。此时正在创建套接字,并且在它绑定之前它不会逃脱内核。这是一个原子操作。当然没有分配临时端口。您在这里与自己的答案相矛盾。
  • 您的声明'端口绑定发生在创建套接字的那一刻'可以解释为对socket() 的调用将导致绑定的套接字,但它不是。在活动连接期间,您可以使用未明确绑定的套接字,因为将分配这样一个临时端口。但我猜你说的是accept() 创建的套接字。我不是有意混淆。
  • @PhilipStuyck 仅当您尚未阅读该问题时。我的回答是关于这个问题,即内核accept() 函数期间做了什么。这与客户端应用程序代码中发生的事情无关。我们能坚持一下吗?
  • @parsecer 数据由元组 {source IP, source port, target IP, target port}, 标识,并且该元组对于连接是唯一的。传入的数据不会进入端口。它转到 TCP,然后从那里转到套接字。
【解决方案3】:

来自 Linux 程序员手册,可通过man 2 accept 找到。 Link

accept() 系统调用与基于连接的套接字一起使用 类型(SOCK_STREAM、SOCK_SEQPACKET)。它提取第一个连接 请求侦听套接字的挂起连接队列, sockfd,创建一个新的连接套接字,并返回一个新文件 引用该套接字的描述符。新创建的套接字不是 处于聆听状态。原始套接字 sockfd 不受 这个电话。

所以发生的情况是您有一个正在侦听的 TCP 套接字。有人请求connect()

然后您拨打accept()。旧的侦听套接字保持在侦听模式,而新的套接字在连接模式下创建。端口是原来的监听端口。

这不会干扰侦听套接字,因为新套接字不会侦听传入连接。

【讨论】:

  • 谢谢!所以套接字中有两种(或更多)模式:LISTENING 和 CONNECTED 对吗?请问一下,DoD模型中when如何解决目标socket?看过几张图通过port连接传输层和应用层,但是port不足以获取目标socket。
  • 那是另一个问题。将其作为另一个问题发布。
  • @ParkJongBin '什么时候以及如何在 DoD 模式下解析目标套接字'和'端口不足以获取目标套接字'意思
  • 他只是在询问每个进入的 tcp 段如何最终馈送到正确的套接字。
  • @PhilipStuyck 他可能会问这个问题,但不简单。例如,“DoD 模型”与它有什么关系?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-10
  • 2013-08-27
  • 2017-02-25
  • 1970-01-01
相关资源
最近更新 更多