блокирующий вариант sub recv my self прочитать байт заголовок FLAP sys

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# блокирующий вариант
sub recv {
my ($self) = @_;
# прочитать 6 байт - заголовок FLAP
sysread $self->socket, my $data, 6;
# в последних двух байтах содержится длина пакета
my $length = unpack('n', substr($data, -2));
# во втором байте - номер канала
my $channel = unpack('C', substr($data, 1, 1));
# читаем данные, размер которых мы извлекли из заголовка
sysread $self->socket, $data, $length;
# теперь у нас есть все для создания OC::ICQ::FLAP
return new OC::ICQ::FLAP($channel, $data);
}
# неблокирующий вариант
sub connect {
my ($self, $host, $port) = @_;
# используем AnyEvent::Handle в качестве абстракции над сокетом для более удобной работы
$self->{io} = new AnyEvent::Handle (
connect => [$host, $port],
# регистрируем колбэки на случай разрыва соединения и ошибки
on_error => sub {$self->on_error(@_)},
on_disconnect => sub {$self->on_disconnect(@_)},
);
# регистрируем колбэк, который будет вызван после того, как из сокета можно будет прочитать 6 байт - заголовок FLAP
$self->{io}->push_read(chunk => 6, sub {$self->on_read_header(@_)});
}
# колбэк, вызываемый при получении заголовка FLAP
sub on_read_header {
my ($self, $io, $header) = @_;
# читаем и запоминаем номер канала - он будет нужен для создания OC::ICQ::FLAP
$self->{flap_channel} = unpack('C', substr($header, 1, 1));
# регистрируем другой колбэк, который будет вызван при получении данных указанного в заголовке размера
$io->push_read(chunk => unpack('n', substr($header, -2)), sub {$self->on_read_data(@_)});
}
# колбэк, вызываемый при получении данных
sub on_read_data {
my ($self, $io, $data) = @_;
# мы получили данные, теперь можно создавать OC::ICQ::FLAP, используя заранее сохраненный номер канала
$self->_process_flap(new OC::ICQ::FLAP($self->{flap_channel}, $data));
# вновь ждем заголовок FLAP
$io->push_read(chunk => 6, sub {$self->on_read_header(@_)});
}