gpt4 book ai didi

perl - 为什么通过 Perl Socket->send() 的 sendto() 忽略对等地址?

转载 作者:行者123 更新时间:2023-12-03 11:59:12 24 4
gpt4 key购买 nike

我有一个使用 IO::Socket::INET->new() 创建的 UDP 套接字的程序(太复杂了,无法在此介绍)两者,Local...Peer...地址和端口。所以期望是一个普通的$sock->send($data, $flags)将发送 $data到创建套接字时指定的对等地址。这似乎有效。

但是,当我尝试使用 $sock->send($data, $flags, $dest) 将单个数据包发送到不同的目的地时, $dest似乎被忽略了(并且数据包被发送到套接字的对等地址)。我添加了很多调试消息,以及参数 $dest正确传递给 send ,但是 strace显示 sendto()NULL 调用为 sockaddr0socklen .
perldoc -f send对我没有帮助。那么为什么目标地址会被忽略呢?

根据要求,这是(有些冗长的)send_packet 代码:

$RE_saddr = qr/^(.+):(\d+)$/;

sub send_packet($$;$)
{
my ($sock, $packet, $dest) = @_;
my @params = ($packet, 0);

if (defined($dest)) {
if (my ($addr, $port) = $dest =~ $RE_saddr) {
if (my $addr_bin = inet_aton($addr)) {
if (defined($dest = sockaddr_in($port, $addr_bin))) {
push(@params, $dest);
} else {
warn "bad address or socket for $addr:$port";
}
} else {
warn "bad address $addr";
}
} else {
warn "bad destination address $dest";
}
}
return 1
if ($sock->send(@params));
return undef;
}

所以很明显,目的地是作为“主机 : 端口”传递的(一个没有空格的字符串(空格是由于这里的标记缺陷))。

最佳答案

如果您使用 Peer*创建 IO::Socket::INET 时然后 connect()将被调用,它设置套接字的对等名称。在这样的套接字上,您永远不必指定远程套接字地址,因为它有一个默认地址。

IO::Socket::send()有一个“功能”:它忽略了 TO套接字具有有效对等名称时的参数:

 my $r = defined(getpeername($sock))
? send($sock, $_[1], $flags)
: send($sock, $_[1], $flags, $peer);

该更改是在 IO 1.12 中引入的,不幸的是,它早于当前的历史 git repository :

Modified IO::Socket::send so not to pass 4 arguments to send if the socket is connected



如果您不喜欢这种行为,则必须使用原始 CORE::send()相反,即:

#!/usr/bin/perl
use warnings;
use strict;

use IO::Socket::INET;
use Socket qw(pack_sockaddr_in);

my $client = IO::Socket::INET->new(
PeerAddr => '127.0.0.1',
PeerPort => 2000,
Proto => 'udp',
) or die "client socket: $!\n";

my $addr = pack_sockaddr_in(2000, inet_aton('127.0.0.1'));

$client->send('ABCD', 0)
or die "IO::Socket::send() no addr: $!\n";
$client->send('ABCD', 0, $addr)
or die "IO::Socket::send() with addr: $!\n";
send($client, 'ABCD', 0, $addr)
or die "send() with addr: $!\n";

exit 0;

测试运行:

$ strace -e sendto,connect,socket perl dummy.pl
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(2000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
sendto(4, "ABCD", 4, 0, NULL, 0) = 4
sendto(4, "ABCD", 4, 0, NULL, 0) = 4
sendto(4, "ABCD", 4, 0, {sa_family=AF_INET, sin_port=htons(2000), sin_addr=inet_addr("127.0.0.1")}, 16) = 4

我的 Linux 机器上的 strace 表明 send()映射到 sendto() ,因为 Perl 代码确实调用了 send() and sendto() .

更新:我创建了 upstream ticket #133936 .

关于perl - 为什么通过 Perl Socket->send() 的 sendto() 忽略对等地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55161627/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com