【问题标题】:How to avoid re-use socket? [closed]如何避免重复使用socket? [关闭]
【发布时间】:2016-05-05 15:37:05
【问题描述】:

有服务器,有客户端。客户端连接到服务器。服务器函数“接受”返回套接字连接的客户端。但是当客户端套接字变得无效时,它可以被重用。如何防止服务器重用同一个socket? P.S.:对于不赞成投票的粉丝,请注意,我不是在问套接字服务器,而是在问客户端套接字。

【问题讨论】:

  • 你为什么要这样做?如果您指定了您要解决的实际问题,则可能有其他方法可以解决它。
  • “我不是在询问套接字服务器,我是在询问客户端套接字。” 非常含糊 - 我假设您的意思是您不是在询问监听套接字。 “如何防止服务器重用同一个套接字?” - 你不能(在我见过的任何实现中),也不应该尝试。至少对于 IP4(我不知道 IP6),端口号是 16 位值,如果例如,你会很快用完。 Web 服务器每次都坚持使用不同的端口号。
  • @MaxZS:每个连接的套接字都以两个 IP:port 端点为特征,并由拥有进程使用文件描述符进行管理。我不知道如何与您的最后评论相协调。一旦一个客户端与服务器的端口 X 断开连接,稍后的 accept() 可能会重新使用相同的服务器端端口号 X:您无法避免这种情况。这是你的问题吗?如果不是,您能否更清楚地重申您的问题?
  • 我同意 TonyD 的观点。正如已经指出的那样,您的术语有些混乱,完全不清楚您在问什么。 “客户端套接字如何变得无效”(您的意思是关闭)?您对“重用套接字”的理解是什么。在 Linux 中,套接字由文件描述符表示。您是说您不希望下一个接受的套接字重用相同的文件描述符值吗?
  • @MaxZS 您需要清楚地说明您遇到的问题。为什么重用服务器上的套接字不好?

标签: c++ c linux sockets


【解决方案1】:

这只是为了澄清一些误解 - 我仍然投票赞成关闭这个问题,除非它被编辑成合理的东西。

但是当客户端socket失效时,可以重用

不,如果 TCP 连接已关闭,则必须关闭套接字文件描述符。稍后可以为新的 TCP 连接分配一个新的套接字,并接收具有相同整数值的文件描述符,但它不是同一个套接字。

套接字——这不仅仅是一个端口,也是地址。

不,套接字是您的进程用来与操作系统讨论 TCP 连接的句柄,该连接本身由包含两个端口和两个地址的 4 元组唯一标识。见this answer,这里就不一一贴了。

如果没有连接,那么客户将不会意识到这一点[关闭套接字]

如果没有连接,就没有什么可以关闭的。

如果有一个现有的 TCP 连接,并且客户端或服务器关闭他们的套接字,则会通知另一端,并且另一端的套接字也将变为无效(并且应该作为响应而关闭)。

例如,socket 有参数 SO_REUSEADDR 和 SO_REUSEPORT。他们为什么要这样做?

当你关闭一个连接时,你会发送一个数据包,告诉连接的另一端你已经这样做了。即使他们承认了这一点,如果它们采用不同的网络路径,您也可以在同一连接上接收其他数据包。因此,TCP 将关闭的连接保持在 TIME_WAIT 状态,防止另一个连接在同一地址:端口元组上启动一段时间,直到它不太可能接收到真正用于前一个连接的数据包。

这个任意的 TIME_WAIT 持续时间是 4 分钟,这很容易让你可以,例如,杀死一个服务器进程然后重新启动它(此时它将无法绑定到它的地址:端口,因为关闭的连接仍在使用该地址:端口)。

SO_REUSEADDR 允许服务器将旧的 TIME_WAIT 连接替换为其新的实时连接。

SO_REUSEPORT 允许多个套接字绑定并接受同一端口以实现负载平衡。

这都是有据可查的,例如。在man page 中,这两个选项都与套接字文件描述符值无关。

正如博洛夫在评论中所说,服务器使用这些的原因是您实际上关心服务器绑定的地址:端口,因为这就是您知道在哪里到达它的方式。客户端连接的本地端口通常是从临时端口范围分配的,没有人关心它的值是什么,只是它在那个时刻是唯一的。

【讨论】:

  • 感谢您对当前讨论中的每个误解做出如此详尽的解释。
【解决方案2】:

这可以通过创建这样的程序来实现,该程序在服务器不接受时释放socket id file descriptor。但这可能会使操作系统复杂化,这可能是操作系统可能出现故障的情况。

file descriptors 可用于 single processfile tableinode table。因为每个file descriptor 都可能由个人inode 指导。

Butinodes 的最大数量在文件系统创建时是固定的,限制了文件系统可以容纳的最大文件数量。文件系统中inodes 的典型分配启发式是总大小的百分之一。

由于indoe table 具有固定大小,并且在发布file descriptor 时,特定的inode 是免费的,但按照您的方式,inode table 可能很快就会干涸并导致系统崩溃。

【讨论】:

  • 您是否暗示通过您的 64k IPv4 端口泄漏可能会耗尽您的 inode(假设它们确实与 inode 相关联)?
  • 我也不是说 IPv4 或 IPv6 端口会耗尽,而是根据套接字 [mapage][1] 返回值,返回文件描述符。 [1]:linux.die.net/man/2/socket
  • 文件描述符不是inode。
  • 是的,你是对的。但是每个文件描述符都有文件表和inode表,也可以有一个inode代表多个文件描述符的情况,但反过来每个文件描述符都属于inode。
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 2020-06-02
  • 2023-04-10
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
相关资源
最近更新 更多