#perl #sockets #moose
#perl #сокеты #moose
Вопрос:
У меня есть объект Moose, который имеет объект ввода-вывода:: Socket::INET в качестве одного из своих атрибутов:
has socket => (
is => 'ro',
required => 1,
lazy => 1,
isa => 'IO::Socket::INET',
builder => 'connect',
);
Сокет инициализируется в скрипте, который выглядит следующим образом (часть аутентификации удалена):
sub connect {
my $self = shift;
my $host = 'A.B.C.D';
my $port = N;
my $handle = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port
) or die "can't connect to port $port on $host: $!";
$handle->autoflush(1);
# Connect to Server with $handle and authenticate
# and if successful .......
return $handle;
}
Однако я нахожу странное поведение при запуске следующего тестового кода:
my $x = MyObject->new;
print $x->socket pack('I', 392);
Байты, полученные Сервером (A.B.C.D), полностью отличаются от тех, которые я отправил. Я проверил, что порядковый номер или порядок байтов не является проблемой. На самом деле простой скрипт, который создает сокет и записывает те же данные без использования Moose, работает идеально — данные поступают на сервер точно так, как ожидалось.
Должен ли я делать что-то большее, чем то, что я делаю, если мой атрибут Moose является постоянным объектом ввода-вывода:: Socket ::INET. Закрывается ли атрибут сокета или каким-либо иным образом манипулируется за моей спиной?
Спасибо.
Комментарии:
1. к вашему сведению,
$handle->autoflush(1);
это уже сделано для вас.2. В моем коде аутентификации была ошибка, из-за которой оставалось на несколько байт больше, чем ожидал сервер, который был прочитан при следующем чтении на сервере. Извините, что потратил впустую время замечательных ребят здесь.
Ответ №1:
print
В документации говорится, что вы должны заключить в блок что-либо более сложное, чем скалярная переменная для дескриптора файла. Вы пробовали:
print { $x->socket } pack ('I', 392);
Или:
$x->socket->print (pack ('I', 392));
Я получаю синтаксическую ошибку, если не ставлю фигурные скобки вокруг $x->socket
.
Следующий код работает для меня. Вы уверены, что что-то не так в разделе аутентификации? Может быть, посмотреть на данные сокета с помощью wireshark?
package Test;
use Moose;
use IO::Socket::INET;
has socket => (
is => 'ro',
required => 1,
lazy => 1,
isa => 'IO::Socket::INET',
builder => 'connect',
);
sub connect {
my $sock = IO::Socket::INET->new (
Proto => "tcp",
PeerAddr => "127.0.0.1",
PeerPort => 2000,
) or die;
$sock;
}
package main;
my $x = Test->new;
print { $x->socket } pack ('I', 392);
Комментарии:
1. Я сделал. Я также попробовал $ x-> socket-> syswrite(pack(‘I’, 392), 4) тоже. Никакой радости : (
2. В моем коде аутентификации действительно была ошибка. Приношу искренние извинения за трату вашего времени и благодарю вас за ваше терпение
Ответ №2:
Я не могу воспроизвести вашу проблему.
Я использовал
use strict;
use warnings;
use IO::Socket::INET;
use Moose;
has socket => (
is => 'ro',
required => 1,
lazy => 1,
isa => 'IO::Socket::INET',
builder => 'connect',
);
sub connect {
my $self = shift;
my $host = 'localhost';
my $port = 12345;
my $handle = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port
) or die "can't connect to port $port on $host: $!";
# Connect to Server with $handle and authenticate
# and if successful .......
return $handle;
}
my $x = __PACKAGE__->new;
print { $x->socket } pack('I', 392);
И я получил
$ nc -l -p 12345 | od -t x1
0000000 88 01 00 00
0000004
Что вы получаете? Что print
вернулось?
Комментарии:
1. Запускался с nc -l 12345, и он выводит правильный результат. Но запустите nc на сервере, и он напечатает мусор.
2. @Gurunandan, То, что вы получаете что-то, означает, что вы правильно получаете сокет от объекта, и что это не имеет никакого отношения к Moose. И теперь вы говорите, что это даже отлично работает для localhost. Время искать в другом месте!
3. Правильно! Мой код аутентификации оставил на несколько байт больше, чем ожидал сервер, который был добавлен к следующему чтению. Приношу искренние извинения за трату вашего времени. Учитывая, что я открыл nc, на самом деле это не было пустой тратой времени. Спасибо!