首页 > 解决方案 > 将 IO::Socket::IP 与 Mojo::IOLoop 一起使用

问题描述

我正在尝试通过 Mojo::IOLoop 和 Mojo::Promises 实现这些代码行同步执行的操作,但异步执行操作:

my $address = '192.168.1.240';

my $sock = IO::Socket::IP->new(PeerAddr => $address,
                          PeerPort => '9999',
                          Proto    => 'tcp');

$sock->send($on);

my $data;

$sock->recv($data, 2048);

print $data;

这用于与 smartplug 通信,基于 Promise 的接口允许我抽象出事物,以便可以以相同的方式处理不同的插件(一些通过 HTTP 通信,一些通过 TCP 通信)。

现在我已经通过这样做取得了结果

sub talk_to_plug_p {
    my ($addr, $command) = @_;

    my $promise =  Mojo::Promise->new;
    my $port = 9999;

    my $sock = IO::Socket::IP->new(PeerAddr => $addr,
                                   PeerPort => $port,
                                   Proto    => 'tcp');

    return $promise->reject("Could not open socket on $addr at port $port") unless $sock;

    my $id = Mojo::IOLoop->client({ handle => $sock } => sub {
                                      my ($loop, $err, $stream) = @_;

                                      $stream->on(read => sub {
                                                      my ($stream, $bytes) = @_;

                                                      # -------------------
                                                      # THIS LOOKS BAD
                                                      # -------------------
                                                      remove_id($loop);
                                                      $promise->resolve($bytes);
                                                  });

                                      $stream->on(error => sub {
                                                      my $err = shift;
                                                      $promise->reject($err);
                                                  });
                                      $stream->write($command);
                                  });

    sub remove_id { shift->remove($id) };

    return $promise;
}

talk_to_plug_p('192.168.1.240', $on)->then(sub { print @_ })->catch(sub { print shift });

Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

现在这可行,但它看起来有点不对 - 特别是remove_id部分,我想必须有比这更好的方法。我只是找不到它。

什么是更清洁的方式?即:在读取字节时关闭客户端,或者我可以显式关闭连接或类似的东西。

标签: perlsocketsmojolicious

解决方案


推荐阅读