EasyTCP
view release on metacpan or search on metacpan
=item *
One easy module to create both clients and servers
=item *
Object Oriented interface
=item *
Event-based callbacks in server mode
=item *
Internal protocol to take care of all the common transport problems
=item *
Transparent encryption
=item *
#
# Create the server object
#
$server = new Net::EasyTCP(
mode => "server",
port => 2345,
)
|| die "ERROR CREATING SERVER: $@\n";
#
# Tell it about the callbacks to call
# on known events
#
$server->setcallback(
data => \&gotdata,
connect => \&connected,
disconnect => \&disconnected,
)
|| die "ERROR SETTING CALLBACKS: $@\n";
#
(Optional and acceptable only when mode is "server")
=back
=back
=head1 METHODS
B<[C] = Available to objects created as mode "client">
B<[H] = Available to "hybrid" client objects, as in "the server-side client objects created when a new client connects". These are the objects passed to your server's callbacks. Such hybrid clients behave almost exactly like a normal "client" object...
B<[S] = Available to objects created as mode "server">
=over 4
=item addclientip(@array)
B<[S]> Adds an IP address (or IP addresses) to the list of allowed clients to a server. If this is done, the server will not accept connections from clients not in it's list.
The compliment of this function is deleteclientip() .
B<[S]> Deletes an IP address (or IP addresses) from the list of allowed clients to a server. The IP address (or IP addresses) supplied will no longer be able to connect to the server.
The compliment of this function is addclientip() .
=item disconnect()
See close()
=item do_one_loop()
B<[S]> Instructs a server object to "do one loop" and return ASAP. This method needs to be called VERY frequently for a server object to function as expected (either through some sort of loop inside your program if you need to do other things beside...
=item encryption()
B<[C][H]> Returns the name of the module used as the encryption module for this connection, undef if no encryption occurs.
=item mode()
B<[C][H][S]> Identifies the mode of the object. Returns either "client" or "server"
=item receive($timeout)
=item socket()
B<[C][H]> Returns the handle of the socket (actually an L<IO::Socket|IO::Socket> object) associated with the supplied object. This is useful if you're interested in using L<IO::Select|IO::Select> or select() and want to add a client object's socket ...
Note that eventhough there's nothing stopping you from reading and writing directly to the socket handle you retrieve via this method, you should never do this since doing so would definately corrupt the internal protocol and may render your connecti...
=item start(subref)
B<[S]> Starts a server and does NOT return until the server is stopped via the stop() method. This method is a simple while() wrapper around the do_one_loop() method and should be used if your entire program is dedicated to being a server, and does ...
If you need to concurrently do other things when the server is running, then you can supply to start() the optional reference to a subroutine (very similar to the callback() method). If that is supplied, it will be called every loop. This is very s...
=item stop()
B<[S]> Instructs a running server to stop and returns immediately (does not wait for the server to actually stop, which may be a few seconds later). To check if the server is still running or not use the running() method.
=back
=head1 COMPRESSION AND ENCRYPTION
Clients and servers written using this class will automatically compress and/or encrypt the transferred data if the appropriate modules are found.
This class implements a miniature protocol when it sends and receives data between it's clients and servers. This means that a server created using this class cannot properly communicate with a normal client of any protocol (pop3/smtp/etc..) unless ...
In other words, if you write a server using this class, write the client using this class also, and vice versa.
=item Delays
This class does not use the fork() method whatsoever. This means that all it's input/output and multi-socket handling is done via select().
This leads to the following limitation: When a server calls one of your callback subs, it waits for it to return and therefore cannot do anything else. If your callback sub takes 5 minutes to return, then the server will not be able to do anything ...
In other words, make the code in your callbacks' subs' minimal and strive to make it return as fast as possible.
=item Deadlocks
As with any client-server scenario, make sure you engineer how they're going to talk to each other, and the order they're going to talk to each other in, quite carefully. If both ends of the connection are waiting for the other end to say something,...
=back
=head1 AUTHOR
Mina Naguib
my %para = @_;
if ($self->{_mode} ne "server") {
$@ = "$self->{_mode} cannot use method setcallback()";
return undef;
}
foreach (keys %para) {
if (ref($para{$_}) ne "CODE") {
$@ = "Callback $_ $para{$_} does not exist";
return 0;
}
$self->{_callbacks}->{$_} = $para{$_};
}
return 1;
}
#
# This method starts the server and does not return until stop() is called.
# All other behavior is delegated to do_one_loop()
#
sub start {
my $self = shift;
$self->{_clients}->{$clientsock}->{_compatabilityreference} = _gencompatabilityreference($self->{_clients}->{$clientsock}->{_compatabilityscalar});
#
# And we make it inherit some stuff from the server :
#
$self->{_clients}->{$clientsock}->{_donotencrypt} = $self->{_donotencrypt};
$self->{_clients}->{$clientsock}->{_donotencryptwith} = $self->{_donotencryptwith};
$self->{_clients}->{$clientsock}->{_donotcompress} = $self->{_donotcompress};
$self->{_clients}->{$clientsock}->{_donotcompresswith} = $self->{_donotcompresswith};
$self->{_clients}->{$clientsock}->{_password} = $self->{_password};
$self->{_clients}->{$clientsock}->{_callbacks} = $self->{_callbacks};
$self->{_clients}->{$clientsock}->{_welcome} = $self->{_welcome};
$self->{_clients}->{$clientsock}->{_selector} = $self->{_selector};
}
}
else {
#
# One of the CLIENT sockets are ready
#
$result = sysread($_, $tempdata, $PACKETSIZE);
}
return $data;
}
#
# This takes a client object and a callback keyword and calls back the associated sub if possible
#
sub _callback {
my $client = shift;
my $type = shift;
if (!$client->{_negotiating} && $client->{_callbacks}->{$type}) {
&{ $client->{_callbacks}->{$type} }($client);
}
}
#
# This sub takes a scalar key
# Returns a reference to a compatability compex object made up of repeating
# the scalar in different combinations
#
sub _gencompatabilityreference {
my $key = shift;
last;
}
}
res($SERVER, "Create new server");
$temp = $SERVER->setcallback(
data => \&gotdata,
connect => \&connected,
disconnect => \&disconnected,
);
res($temp, "Set callbacks");
}
sub startserver {
$SERVER->start();
}
sub startclient {
my $temp;
my $pid;
util/server.pl view on Meta::CPAN
$| = 1;
print "Creating server ...\n";
$server = new Net::EasyTCP(
mode => "server",
port => 2345,
welcome => "Welcome to my first little echo server",
)
|| die "ERROR CREATING SERVER: $@\n";
print "Setting callbacks ...\n";
$server->setcallback(
data => \&gotdata,
connect => \&connected,
disconnect => \&disconnected,
)
|| die "ERROR SETTING CALLBACKS: $@\n";
print "Starting server ...\n\n";
$server->start() || die "ERROR STARTING SERVER: $@\n";
( run in 0.384 second using v1.01-cache-2.11-cpan-9b1e4054eb1 )