Perl和服务器 - 客户端套接字

时间:2018-03-09 08:26:27

标签: perl sockets tcp

背景/背景

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

我被卡住了。

今天下午,我一直在寻找一个彻底的解释,其中的例子涵盖了Perl和TCP套接字的所有内容。来自谷歌的大量结果仍然列出了2007 - 2012年的文章。看来最初有'Socket'模块,随着时间的推移IO :: Socket被添加,然后是IO :: Select。但是Perldoc页面不会在一个地方覆盖或引用所有内容,或者提供足够的交叉引用链接。我认为Socket中的大多数原始调用在IO :: Socket中都有一个等价物。如果通过OO模块无法获得某些功能,那么它可能(推荐?是/否?)在套接字上进行功能调用...

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

我一直在尝试今天遇到的所有内容,包括调用can_read,has_exception的IO :: Select,但无论socket是up还是down,这些输出都没有显示差异 - 我从netstat输出确认为non OS(MacOS)立即拆除了阻塞套接字。

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

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

从其他C和Java doco页面,我收集有一个返回undef,0,> 0的约定,并且在某些实现上-1执行相当于sysread的操作。是否有官方perl规范有人可以链接我描述Perl实施的内容? sysread或recv是首先从TCP套接字读取的“正确”方式吗?

我这里没有提供我的代码,因为我从“最佳实践”的角度提出问题,进行客户端 - 服务器通信的'正确'方式是什么?投票甚至是正确的开始方式吗?是否有一种事件驱动的方法,我已经错过了..

如果我所要求的内容已经可用,我真诚地道歉,但谷歌一直给我相同的旧结果页面和我已阅读过的衍生博客/文章。

非常感谢提前。

1 个答案:

答案 0 :(得分:5)

  

如果无法通过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完成,以便不返回来自底层OS套接字的数据,而是从SSL套接字返回解密数据。

  

从其他C和Java doco页面,我收集有一个返回undef,0,> 0的约定,并且在某些实现上-1执行相当于sysread的操作。是否有官方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