Last active
May 16, 2018 15:42
-
-
Save Logioniz/c706a62a99f27ec05e400e6111b36187 to your computer and use it in GitHub Desktop.
UPD server/client example (block/nonblock)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use Mojo::Base -strict; | |
use Socket ':all'; | |
socket(my $client, AF_INET, SOCK_DGRAM, IPPROTO_UDP) || die "socket: $!"; | |
bind($client, pack_sockaddr_in(7777, inet_aton('192.168.88.114'))); | |
send($client, "hi, vasya", 0, pack_sockaddr_in(12345, inet_aton('192.168.88.114'))); | |
my $peer = recv($client, my $msg, 2048, 0); | |
my ($port, $addr) = unpack_sockaddr_in($peer); | |
my $peer_ip = inet_ntoa($addr); | |
say "$port $peer_ip: $msg"; | |
send($client, "hi, vasya 2", 0, $peer); | |
send($client, "hi, vasya 3", 0, pack_sockaddr_in(12345, inet_aton('192.168.88.114'))); | |
send($client, "hi, vasya 4", 0, pack_sockaddr_in(12345, inet_aton('127.0.0.1'))); | |
socket($client, AF_INET, SOCK_DGRAM, IPPROTO_UDP) || die "socket: $!"; | |
send($client, "hi, vasya 5", 0, pack_sockaddr_in(12346, inet_aton('127.0.0.1'))); | |
close $client; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use Mojo::Base -strict; | |
use Socket ':all'; | |
socket(my $server, AF_INET, SOCK_DGRAM, IPPROTO_UDP) || die "socket: $!"; | |
setsockopt $server, SOL_SOCKET, SO_REUSEADDR, 1; | |
bind $server, pack_sockaddr_in(12345, INADDR_ANY); | |
while (my $peer = recv($server, my $msg, 2048, 0)) { | |
my ($port, $addr) = unpack_sockaddr_in($peer); | |
my $peer_ip = inet_ntoa($addr); | |
say "$port $peer_ip: $msg"; | |
send($server, "hi, petya", 0, $peer); | |
} | |
close $server; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
package IOLoop; | |
use Mojo::Base -base; | |
use IO::Poll; | |
use IO::Poll 'POLLPRI'; | |
use List::Util 'min'; | |
use Time::HiRes 'time'; | |
sub new { | |
my $self = shift->SUPER::new(@_); | |
$self->{poll} = IO::Poll->new; | |
return $self; | |
} | |
sub add { | |
my ($self, $handle, $read, $write, $cb) = @_; | |
my $mask = 0; | |
$mask |= POLLIN | POLLPRI if $read; | |
$mask |= POLLOUT if $write; | |
$self->{poll}->mask($handle => $mask); | |
$self->{io}{$handle} = $cb; | |
return $self; | |
} | |
sub remove { | |
my ($self, $handle) = @_; | |
$self->{poll}->remove($handle); | |
delete $self->{io}{$handle}; | |
return $self; | |
} | |
sub timer { | |
my ($self, $delay, $cb) = @_; | |
my $moment = time + $delay; | |
$self->{timer}{$cb}{moment} = $moment; | |
$self->{timer}{$cb}{cb} = $cb; | |
return $self; | |
} | |
sub one_tick { | |
my $self = shift; | |
my $min_time = min map { $self->{timer}{$_}{moment} } keys %{$self->{timer}}; | |
$min_time = defined $min_time ? $min_time - time : 1; | |
$min_time = $min_time < 0 ? 0 : $min_time; | |
my $num = $self->{poll}->poll($min_time); | |
my @handles = $self->{poll}->handles(POLLIN | POLLPRI); | |
for (@handles) { | |
my $cb = $self->{io}{$_}; | |
$self->$cb(0); | |
} | |
@handles = $self->{poll}->handles(POLLOUT); | |
for (@handles) { | |
my $cb = $self->{io}{$_}; | |
$self->$cb(1); | |
} | |
my $now = time; | |
for my $timer (keys %{$self->{timer}}) { | |
if ($self->{timer}{$timer}{moment} <= $now) { | |
my $cb = $self->{timer}{$timer}{cb}; | |
$self->$cb(); | |
delete $self->{timer}{$timer}; | |
} | |
} | |
return $self; | |
} | |
sub start { | |
my $self = shift; | |
$self->{run} = 1; | |
$self->one_tick while $self->{run}; | |
return $self; | |
} | |
sub stop { | |
my $self = shift; | |
$self->{run} = 0; | |
return $self; | |
} | |
package UPDServer; | |
use Mojo::Base -base; | |
use Socket ':all'; | |
has 'handle'; | |
has 'ioloop'; | |
sub new { | |
my $self = shift->SUPER::new(@_); | |
$self->{ioloop} = IOLoop->new; | |
return $self; | |
} | |
sub create { | |
my ($self, $port) = @_; | |
socket(my $server, AF_INET, SOCK_DGRAM, IPPROTO_UDP) || die "socket: $!"; | |
setsockopt $server, SOL_SOCKET, SO_REUSEADDR, 1; | |
bind $server, pack_sockaddr_in($port // 12345, INADDR_ANY); | |
return $self->handle($server); | |
} | |
sub start { | |
my ($self, $cb) = @_; | |
$self->ioloop->add($self->handle, 1, 0, sub { | |
my $peer = recv($self->handle, my $msg, 40, 0); | |
$cb->($self->ioloop, $self->handle, $peer, $msg); | |
}); | |
$self->ioloop->start; | |
} | |
package main; | |
use Mojo::Base -strict; | |
use Socket ':all'; | |
my $server = UPDServer->new; | |
$server->create->start(sub { | |
my ($ioloop, $server, $peer, $msg) = @_; | |
my ($port, $addr) = unpack_sockaddr_in($peer); | |
my $peer_ip = inet_ntoa($addr); | |
say "$port $peer_ip: $msg"; | |
$ioloop->timer(5, sub { | |
send($server, "hi, petya", 0, $peer); | |
}) | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment