Windows 上 Strawberry 上的 Perl 程序需要“使用 POSIX”才能评估 <$sock> 并从端口读取数据包

0 windows perl posix handle

Perl 程序读取 UDP 数据包并清理数据并传输到另一个端口。
如果没有use POSIX;在程序中,它就不能变成<$sock>数据包。

`$sock` comes from:
Run Code Online (Sandbox Code Playgroud)
`$sock` comes from:
Run Code Online (Sandbox Code Playgroud)

数据正确输入use POSIX

!AIVDM,1,1,,B,37Oms:?Oh0bHEEMb=j5A5AtL00N0,0*76" (AIS data)
without that, <$data> appears as "GLOB(0x1563bcda6e8)
Run Code Online (Sandbox Code Playgroud)

PERldocs“强烈反对”使用“use POSIX;” https://perldoc.perl.org/POSIX

    socket($sock, PF_INET, SOCK_DGRAM, getprotobyname('udp'))
    bind($sock, $sockets[0])
Run Code Online (Sandbox Code Playgroud)

应该从套接字给我数据,不带use POSIX; 此时它挂起。

hob*_*bbs 5

首先,您应该添加use strict,它会告诉您为什么您的程序在没有 POSIX: 的情况下无法工作:PF_INET并且SOCK_DGRAM没有定义。启用严格性后,您会收到类似错误

Bareword "PF_INET" not allowed while "strict subs" in use at...
Bareword "SOCK_DGRAM" not allowed while "strict subs" in use at...
Run Code Online (Sandbox Code Playgroud)

然后您可以通过添加来修复

use POSIX qw(PF_INET SOCK_DGRAM);
Run Code Online (Sandbox Code Playgroud)

或者通过添加

use POSIX ();
Run Code Online (Sandbox Code Playgroud)

并参考POSIX::PF_INETPOSIX::SOCK_DGRAM,如文档所示。只从 POSIX 导入所有内容,这是一个糟糕的主意。

问题是,如果您不导入并且使用 strict,您将传递字符串 "PF_INET""SOCK_DGRAM"to socket,这会被默默地解释为完全错误的东西(可能是与 number 对应的任何套接字类型和协议0)。套接字创建可能完全失败,但您没有检查$!错误,因此您永远不会发现它。

然而,

使用 90 年代的任何东西都是Socket相当POSIX的。它迫使您执行大量容易出错的手动工作,并且需要对 IPv4 和 IPv6 进行不同的调用。在 perl 5.20+ 上你可以改为

use IO::Socket::IP;
my $sock = IO::Socket::IP->new(Proto => 'udp', LocalPort => $port)
    or die "listening on udp/$port: $IO::Socket::errstr";
Run Code Online (Sandbox Code Playgroud)

它用一个更易读的调用替换了对sockaddr_ingetprotobynamesocket、 和 的调用。bind您从中获得的套接字的工作方式与您从 中获得的套接字的工作方式完全相同socket

如果由于某种原因你的 perl 已经超过 9 年了,你可以IO::Socket::INET使用IO::Socket::IP. 除了 IPv6 支持之外,它的工作原理类似,并且自 2000 年以来一直处于核心地位。

如果您正在阅读的教程或其他内容告诉您如何以 25 年前过时的方式做事,您可能想扔掉它。