Skip to content

Instantly share code, notes, and snippets.

@cooldaemon
Created September 14, 2008 10:01
Show Gist options
  • Save cooldaemon/10722 to your computer and use it in GitHub Desktop.
Save cooldaemon/10722 to your computer and use it in GitHub Desktop.
Echo server made from Danga::Socket.
package Echo::Client;
use strict;
use warnings;
use IO::Socket::INET;
use Danga::Socket;
use Danga::Socket::Callback;
sub new {
my $class = shift;
my ($host, $port) = @_;
my $self = bless {}, $class;
$self->{socket} = Danga::Socket::Callback->new(
handle => $self->_connect($host, $port),
on_read_ready => sub {$self->_read},
);
Danga::Socket->SetPostLoopCallback(sub {
return $self->{socket}->{closed} ? 0 : 1;
});
return $self;
}
sub _connect {
my $self = shift;
my ($host, $port) = @_;
my $socket = IO::Socket::INET->new(
PeerAddr => $host,
PeerPort => $port,
Blocking => 0,
) or die "Error creating socket: $@";
$socket->blocking(0);
return $socket;
}
sub _read {
my $self = shift;
my $buffer_ref = $self->{socket}->read(1_000);
return $self->{socket}->close if !defined $buffer_ref;
$self->{recv} .= $$buffer_ref;
}
sub send {
my $self = shift;
my ($message) = @_;
$self->{socket}->write($message);
}
sub recv {
my $self = shift;
Danga::Socket->EventLoop;
return $self->{recv};
}
1;
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin qw($Bin);
use lib $Bin . '/lib';
use Echo::Client;
my $port = shift || die "Usage: $0 port\n";
my $echo = Echo::Client->new('127.0.0.1', $port,);
for (qw(foo bar baz bye)) {
$echo->send($_ . "\n");
}
print $echo->recv;
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin qw($Bin);
use lib $Bin . '/lib';
use Echo::Server;
my $port = shift || die "Usage: $0 port\n";
Echo::Server->new($port)->run;
package Echo::Server;
use strict;
use warnings;
use IO::Socket::INET;
use Socket qw(SOCK_STREAM IPPROTO_TCP TCP_NODELAY);
use IO::Handle;
use Danga::Socket;
use Danga::Socket::Callback;
sub new {
my $class = shift;
my ($port) = @_;
my $self = bless {
socket => $class->_connect($port),
}, $class;
Danga::Socket->AddOtherFds(
fileno($self->{socket}) => sub {$self->_accept}
);
return $self;
}
sub _connect {
my $class = shift;
my ($port) = @_;
my $socket = IO::Socket::INET->new(
LocalPort => $port,
Type => SOCK_STREAM,
Proto => IPPROTO_TCP,
Blocking => 0,
Reuse => 1,
Listen => 10
) or die "Error creating socket: $@";
$socket->blocking(0);
return $socket;
}
sub _accept {
my $self = shift;
my $socket = $self->{socket}->accept;
return if !$socket;
$socket->autoflush(1);
$socket->blocking(0);
IO::Handle::blocking($socket, 0);
setsockopt(
$socket, IPPROTO_TCP, TCP_NODELAY, pack('l', 1)
) or die "Error setting socket option.";
Danga::Socket::Callback->new(
handle => $socket,
on_read_ready => sub {$self->_read(shift)},
);
}
sub _read {
my $self = shift;
my ($socket) = @_;
my $buffer_ref = $socket->read(1_000);
return $socket->close unless defined $buffer_ref;
$socket->write($buffer_ref);
return if $$buffer_ref !~ /^bye/m;
$socket->write("cya\n");
$socket->close;
}
sub run {
Danga::Socket->EventLoop;
}
1;
@hrchu
Copy link

hrchu commented Apr 24, 2018

made from Danga::Socket::Callback instead of pure Danga::Socket

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment