【问题标题】:Perl socket sending hashPerl 套接字发送哈希
【发布时间】:2012-12-05 02:35:34
【问题描述】:

我正在尝试在 Perl 中创建一个套接字客户端。服务器端是一个运行在本地主机上的C程序。

我必须通过套接字发送散列。这是我正在使用的一段代码。

sub applyGlobalConfig {
    my ($globalConfig, $ignoreData) = @_;

    my $socket = IO::Socket::INET->new(PeerAddr => $PEER_HOST,
                                       PeerPort => $PEER_PORT,
                                       Proto    => "tcp",
                                       Type     => SOCK_STREAM)
          or die "Couldn't connect to $PEER_HOST:$PEER_PORT : $@\n";

    my $reconfigResult;

    print $socket "$113\n";

    close($socket);

    unless ($reconfigResult) {
        return 0;
    }

    return ERR_NULL;
}

现在,我的问题是,$globalConfig 将包含一个哈希引用,我想通过套接字发送它。我无法弄清楚。我在谷歌上搜索并找到了一些关于 Dumper 的参考资料,但不太了解。如何发送哈希?

【问题讨论】:

  • 您希望将哈希引用作为数字还是作为字符串发送(仅用于引用的值),还是希望发送哈希的内容(递归)?问题不清楚,发送“113 美元”也是如此。

标签: perl sockets


【解决方案1】:

要通过套接字发送数据结构,您必须将其“序列化”为字节流。然后接收程序必须对其进行反序列化以重新组装数据结构。如果接收程序期望流采用特定格式,则发送程序必须生成期望的格式。

如果您同时编写双方,那么您可以选择一种对您的情况有意义的序列化格式,例如 JSON 或 XML,这两种格式都可以表示 Perl 哈希。但是,在不了解您的具体情况的更多细节的情况下,这就是可以以答案的方式提供的所有信息。

【讨论】:

    【解决方案2】:

    我更愿意为此使用Storable 模块。示例:

    接收端:

    use strict;
    use IO::Socket::INET;
    use Storable;
    use Data::Dumper;
    
    my   $sock = IO::Socket::INET->new(Listen    => 5, LocalAddr => 'host',
                                     LocalPort => 9000,  Proto     => 'tcp');
    while( my $s = $sock->accept ) {
        my $struct = Storable::fd_retrieve($s);
        print Dumper($struct);
    }
    

    发送端:

    use strict;
    use IO::Socket::INET;
    use Storable;
    
    my   $sock = IO::Socket::INET->new(PeerAddr => 'host',  PeerPort => 9000,
                     Type     => SOCK_STREAM, Proto     => 'tcp') || die "Fail: $!";
    my $struct = {
        a => 1,
        b => [2,3,4]
    };
    Storable::nstore_fd($struct, $sock);
    

    通过从 i386 Linux 发送到 amd64 FreeBSD 进行测试。

    您也可以使用 Data::Dumper 从哈希生成字符串,然后通过网络发送,但它的方法很脏且有问题。

    UPD:

    但是,我正在努力如何将 perl 端的哈希值转换为以空格分隔的字符串。

    尝试使用join/map组合:

    my $serialized = join("\n", map { "$_ ".$struct->{$_} } keys %$struct)."\n";
    

    可能在 C 端它更容易使用以空字符结尾的字符串:

    my $keyvalue_count = scalar keys(%$struct);
    my $serialized = join("\0", map { "$_\0".$struct->{$_} } keys %$struct)."\0";
    

    在这种简单的情况下,我更喜欢使用最后一个变体,因为它是 C 原生的。

    【讨论】:

    • 接收器是用 C 语言编写的......但也许它只是存储数据以供 Perl 稍后检索?
    • @ikegami Opps 我没能记住这一点。在这种情况下,它真的更复杂,因为普通 C 中的哈希实现不是一个简单的问题。使用 perlembed 可能值得坚持使用 Storable::fd_retrieve。或者也许只是发送像key = value\n这样的文本
    • 正如ikegami所说,服务器是一个c程序。它接收这些作为包含 argc 和 argv 的结构。我在想的一种方法是将散列中的值转换为用空格分隔的字符串。在发送之前。但是,我正在努力如何将 perl 端的哈希值转换为用空格分隔的字符串。感谢任何帮助
    • 看起来不错。让我试试。顺便说一句,我不能使用我的 $globalData = sprintf ("%s %s %s\n", $OPCODE, $cfg->{"hisAge"}, $cfg->{"herAge"}) 然后做打印 $socket $globalData;
    • @SreeramRavinooothala 当然可以,但是添加新的哈希键可能会很痛苦
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多