Skip to content

Instantly share code, notes, and snippets.

@Logioniz
Last active May 16, 2018 15:42
Show Gist options
  • Save Logioniz/c706a62a99f27ec05e400e6111b36187 to your computer and use it in GitHub Desktop.
Save Logioniz/c706a62a99f27ec05e400e6111b36187 to your computer and use it in GitHub Desktop.
UPD server/client example (block/nonblock)
#!/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;
#!/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;
#!/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