与“连接”的perl` send``发送陷阱'' udp`io :: socket :: inet`忽略目标地址?
当通过INET UDP套接字发送的数据包是不是发送到给定目标地址的时,我正在调试一些奇数问题。
文档(perldoc -f send
)说:
在未连接的插座上,您必须指定发送到达的目的地,在这种情况下,它会执行Sendto(2)Syscall。
这就是关于to
参数连接的插座的全部内容。
但是,经过数小时的调试,手册似乎不是说的是:
在连接的插座上忽略了参数。
所以我想知道:
- UDP插座是否 connected ?
- 我发现正确的是,当创建
peeraddr
时,send
的参数被忽略了“连接”插座)? - 当“连接”插座并指定目标地址时,是否应该发送返回错误,或者实现错误(即:发送时给定的目标在发送时是否应该覆盖插座的对等地址)?至少这遵循至少令人惊讶的原则。
一个示例
是提供一个示例,以下是一个:
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket;
sub _socket(;$$)
{
my ($l, $p) = @_;
my %params = ('Proto' => 'udp');
@params{'LocalAddr', 'LocalPort'} = split(/:/, $l)
if ($l);
@params{'PeerAddr', 'PeerPort'} = split(/:/, $p)
if ($p);
return IO::Socket::INET->new(%params);
}
my $sock1 = _socket('localhost:1514');
my $sock2 = _socket('localhost:0', 'localhost:1514');
my $pkt;
while (defined(my $peer = $sock1->recv($pkt, 1000, 0))) {
print "received $pkt\n";
$sock2->send("response " . $pkt, 0, $peer);
}
运行它,在同一主机上尝试netcat -u localhost 1514
。 然后输入“垃圾”之类的一行,您会发现示例程序不会发送回发送者,而是将其发送给循环。
在strace
下运行示例,我看到connect()
用于“连接” $ sock2
。
I'm debugging some odd issue when a packet sent via an INET UDP socket is not sent to the given destination address.
The documentation (perldoc -f send
) says:
On unconnected sockets, you must specify a destination to send to, in which case it does a sendto(2) syscall.
That's all it says about the TO
parameter an connected sockets.
However after hours of debugging it seems what the manual does not say is:
On connected sockets the TO parameter is being ignored.
So I'd like to know:
- Are UDP sockets ever connected?
- Is my finding correct that the TO parameter for
send
is being ignored whenPeerAddr
was specified when creating aIO::Socket::INET
(thus "connecting" the socket)? - Shouldn't send return an error when the socket is "connected" and a destination address is specified, or is the implementation faulty (i.e.: Shouldn't a given destination override the socket's peer address when sending)? At least that would follow the principle of least surprise.
A kind of an example
As it was requested to provide an example, here is one:
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket;
sub _socket(;$)
{
my ($l, $p) = @_;
my %params = ('Proto' => 'udp');
@params{'LocalAddr', 'LocalPort'} = split(/:/, $l)
if ($l);
@params{'PeerAddr', 'PeerPort'} = split(/:/, $p)
if ($p);
return IO::Socket::INET->new(%params);
}
my $sock1 = _socket('localhost:1514');
my $sock2 = _socket('localhost:0', 'localhost:1514');
my $pkt;
while (defined(my $peer = $sock1->recv($pkt, 1000, 0))) {
print "received $pkt\n";
$sock2->send("response " . $pkt, 0, $peer);
}
Run it, and on the same host try netcat -u localhost 1514
.
Then enter one line like "junk", and you'll see that the sample program does not send back to the sender, but to itself, causing a loop.
Running the example under strace
, I see that connect()
is being used to "connect" $sock2
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有关系统调用的详细信息,例如
connect
和发送
,请参阅您的系统的MAN页面。on Posix Systems上
因此,使用
连接
覆盖您可能在其他地方提供的任何目标地址。错误noreferrer“> docs 指示错误
eisconn
“在“指定目标地址并已经连接插座”时,可能会或可能不会返回连接模式插座。”现在,我尚不清楚是什么使插座成为“连接模式套接字”,但它似乎基于协议。但是,鉴于明显缺乏连接的UDP插座的其他指导,我发现可以合理地期望与TCP这样的协议相同的行为。也就是说,地址被忽略或返回错误
eisconn
。See your system's man pages for details on systems calls such as
connect
andsend
.On POSIX systems,
connect
saysSo using
connect
overrides any destination address you might provide elsewhere.The docs indicate error
EISCONN
"may or may not be returned for connection mode sockets" when "a destination address was specified and the socket is already connected."Now, it's not clear to me what makes a socket a "connection mode socket", but it appears to be based on protocol. But given an apparent lack of other guidance for connected UDP sockets, I find it reasonable to expect the same behaviour as for protocols like TCP. That is, the address is ignored or error
EISCONN
is returned.