【问题标题】:Perl and server-client socketsPerl 和服务器-客户端套接字
【发布时间】:2023-04-05 21:07:01
【问题描述】:

背景/上下文

我有两个脚本,一个可以处理多个客户端的服务器端脚本,一个连接到服务器的客户端脚本。任何向服务器发送消息的客户端都会将该消息复制/回显给所有其他连接的客户端。


我被困在哪里。

今天下午,我一直在凭空寻找一个详尽的解释,其中包含有关 Perl 和 TCP 套接字的所有示例。来自 google 的大量搜索结果仍然列出了 2007-2012 年的文章。似乎最初有 'Socket' 模块,随着时间的推移,添加了 IO::Socket,然后添加了 IO::Select。但是 Perldoc 页面并没有在一个地方涵盖或引用所有内容,或者提供足够的交叉引用链接。我收集到 Socket 中的大多数原始调用在 IO::Socket 中都有一个等价物。如果某些东西不能通过 OO 模块获得,它可能(推荐?是/否?)在套接字上进行功能调用......

问题1.远端/对端已断开/套接字不再建立?

我一直在尝试我今天遇到的所有事情,包括调用 can_read、has_exception 的 IO::Select,但是无论套接字是打开还是关闭,这些输出都没有差异 - 我从 netstat 输出确认非-阻塞套接字被操作系统(MacOS)立即拆除。

问题 2. 是否有数据可供读取?

对于我以前的 perl 客户端脚本,我已经推出了自己使用 sysread (https://perldoc.perl.org/functions/sysread.html) 的方法,但今天我注意到 recv 列在此页面顶部 https://perldoc.perl.org/IO/Socket.html 附近的概要中,但是有在下面的详细信息中没有提到recv方法...

从其他 C 和 Java 文档页面中,我收集到在执行与 sysread 等效时返回 undef、0、>0 和在某些实现上返回 -1 的约定。是否有人可以将我链接到描述 Perl 实现的官方 perl 规范? sysread 或 recv 是首先从 TCP 套接字读取的“正确”方式吗?

我没有在这里提供我的代码,因为我从“最佳实践”的角度询问,进行客户端-服务器通信的“正确”方式是什么?民意调查甚至是正确的开始方式吗?有没有我错过的事件驱动方法..

如果我所要求的内容已经可用,我深表歉意,但 google 一直为我提供与我已经阅读过的相同的旧结果页面和衍生博客/文章。

非常感谢。

【问题讨论】:

  • 这个类似于聊天服务器;也许选择一些已经存在的(Mojolicious?)而不是重新发明轮子,除非是出于教育目的。
  • 谢谢,但我已经看过几个聊天服务器实现,但他们没有回答我的问题。像往常一样,在学习某些东西时,通常需要先从一个简单的例子开始,然后才能将其应用于更复杂的案例。 :) 但无论如何感谢您的回复。

标签: perl sockets tcp


【解决方案1】:

如果无法通过 OO 模块获得某些内容,则可以(推荐?是/否?)对套接字进行功能调用...

我不确定您所指的哪些函数调用在 IO::Socket 中不可用。但总的来说 IO::Socket 对象也是普通的文件句柄。这意味着您可以执行$server->accept 之类的操作,也可以执行accept($server) 之类的操作。

问题 1. 远端/对端已断开/套接字不再 ESTABLISHED?

这个问题不是 Perl 特有的,而是select 和套接字 API 的一般工作方式。 Perl 在这方面没有添加它自己的行为。一般来说:如果对等方已关闭连接,则select 将显示套接字可用于读取,如果对套接字进行读取,它将不返回任何数据和错误 - 这意味着没有更多数据可用于从对等方读取,因为对等方已正确关闭其一侧的连接(连接关闭不被视为错误,而是正常行为)。请注意,即使对等方已指示它将不再发送任何数据,TCP 内仍有可能向对等方发送数据。

问题 2. 是否有数据可供读取?

sysreadrecvreadrecv/recvmsg 不同,或者在底层 libc 中不同。特别是recv 可以有标志,例如允许在不读取数据的情况下查看系统套接字缓冲区中可用的数据。请参阅the documentation 了解更多信息。

我建议使用sysread 而不是recv,因为sysread 的行为可以在tying a file handle 时重新定义,而recv 的行为则不能。例如,绑定文件句柄由IO::Socket::SSL 完成,因此不会返回来自底层操作系统套接字的数据,而是来自 SSL 套接字的解密数据。

从其他 C 和 Java 文档页面中,我了解到在执行等效 sysread 时返回 undef、0、>0 和在某些实现上返回 -1 的约定。是否有人可以将我链接到描述 Perl 实现的官方 perl 规范?

sysread 的行为有据可查。引用使用perldoc -f sysread时得到的内容:

... 返回字节数 实际读取,文件末尾为 0,如果有错误,则为 undef (在后一种情况下,还设置了 $!)。

除此之外,您将您的问题陈述为 是否有数据可供读取? 但是您只谈论sysreadrecv,而不是如何在调用之前检查数据是否可用这些功能。我假设您正在使用select(或 IO::Select,它只是一个包装器)来执行此操作。虽然 IO::Select 的can_read 在大多数情况下可用于获取信息,但它只会从底层 OS 套接字返回信息。使用普通套接字就足够了,但是例如,当使用 SSL 时,SSL 堆栈中会进行一些内部缓冲,即使缓冲区中仍有可读取的数据,can_read 也可能返回 false。请参阅Common Usage Errors: Polling of SSL sockets 了解如何正确处理此问题。

【讨论】:

  • 谢谢!这有助于填补我的一些空白。我现在不记得为什么我在 sysread func 本身上打折了 perldoc 页面。我想我期待一个单独的页面或文档概述套接字/ipc 上下文中的行为。
猜你喜欢
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 2013-11-11
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 2012-02-12
相关资源
最近更新 更多