NAME
Net::Socket::NonBlock - Perl extension for easy creation multi-socket single-thread application, especially non-forking TCP servers
Version 0.04
SYNOPSIS
# TCP port forwarder with logging
# Works on Win32!
use strict;
use Net::Socket::NonBlock qw(SafeStr);
$| = 1;
my $LocalPort = shift
or die "Usage: $0 <LocalPort> <RemoteHost:RemotePort>\n";
my $RemoteHost = shift
or die "Usage: $0 <LocalPort> <RemoteHost:RemotePort>\n";
my $SockNest = Net::Socket::NonBlock->new(SelectT => 0.1,
SilenceT => 0,
debug => $^W,
BuffSize => 10240,
)
or die "Error creating sockets nest: $@\n";
$SockNest->Listen(LocalPort => $LocalPort,
Proto => 'tcp',
Accept => \&NewConnection,
SilenceT => 0,
#ClientsST => 10,
Listen => 10,)
or die "Could not listen on port \"$LocalPort\": $@\n";
my %ConPool = ();
while($SockNest->IO())
{
my $Pstr = '';
my $ClnSock = undef;
my $SrvSock = undef;
while (($ClnSock, $SrvSock) = each(%ConPool))
{
my $ClientID = sprintf("%15.15s:%-5.5s", $SockNest->PeerAddr($ClnSock), $SockNest->PeerPort($ClnSock));
my $Str = undef;
while(($Str = $SockNest->Read($ClnSock)) && length($Str))
{
$Pstr .= " $ClientID From CLIENT ".SafeStr($Str)."\n";
$SockNest->Puts($SrvSock, $Str);
};
if (!defined($Str))
{
$Pstr .= " $ClientID CLIENT closed\n";
$SockNest->Close($ClnSock);
$SockNest->Close($SrvSock);
delete($ConPool{$ClnSock});
next;
};
while(($Str = $SockNest->Read($SrvSock)) && length($Str))
{
$Pstr .= " $ClientID From SERVER ".SafeStr($Str)."\n";
$SockNest->Puts($ClnSock, $Str);
};
if (!defined($Str))
{
$Pstr .= " $ClientID SERVER closed\n";
$SockNest->Close($ClnSock);
$SockNest->Close($SrvSock);
delete($ConPool{$ClnSock});
next;
};
};
if (length($Pstr))
{ print localtime()."\n".$Pstr; };
};
sub NewConnection
{
my ($ClnSock) = shift
or return;
$ConPool{$ClnSock} = $SockNest->Connect(PeerAddr => $RemoteHost, Proto => 'tcp',);
if(!$ConPool{$ClnSock})
{
warn "Can not connect to \"$RemoteHost\": $@\n";
$SockNest->Close($ClnSock);
delete($ConPool{$ClnSock});
return;
};
return 1;
};
DESCRIPTION
This module provides simple way to work with number of non-blocking sockets. It hides most of routine operations with IO::Socket::INET
, IO::Select
and provides you the asynchronous Input-Output functions.
Module was designed as a part of a multi-connection SMTP relay for WinNT platform.
The Net::Socket::NonBlock
methods
new(%PARAMHASH);
-
The
new
method creates theSocketsNest
object and returns a handle to it. This handle is then used to call the methods below.The
SocketsNest
itself is the table contains socket handlers, InOut buffers, etc.SocketsNest
also contain aIO::Select
object which is common for all sockets inSocketsNest
.To create new socket you will have to use
Listen
orConnect
methods (see below). Also, socket could be created automatically during TCP connection accept procedure inside ofIO
method.The %PARAMHASH could contain the following keys:
-
SelectT
-
SelectT
is the timeout forIO::Select->can_read
andIO::Select->can_write
function. See IO::Select for details. Default is 0.1 second. SilenceT
-
If no data was transferred trough socket for
SilenceT
seconds the socket will be closed. Default is '0'. IfSilenceT = 0
socket will nether been closed by timeout.This value is the default for all sockets created by
Listen
orConnect
method if another value will not be provided inListen
orConnect
parameters. Also, you will be able to change this parameter for any socket in nest usingProperties
method (see below). BuffSize
-
The size of buffer for
IO::Socket::INET->recv
function (see IO::Socket::INET). Default ifPOSIX::BUFSIZ
(seePOSIX
).This is default for all sockets which will be created and could be overwritten by
Listen
,Connect
orProperties
. debug
-
If true, additional debug info will be printed during program execution.
-
IO();
-
The most important method :) This method performs actual socket input-output, accept incoming connection, close sockets, etc. You have to call it periodically, as frequently as possible.
IO
always returns 1. SelectT([$Timeout]);
-
If
$Timeout
is not specified theSelectT
method returns a current value ofSelectT
.If
$Timeout
is specified theSelectT
method set theSelectT
to the provided value and returns a previous one.
The Net::Socket::NonBlock
methods for manipulating sockets
Listen(%PARAMHASH);
-
The
Listen
method create new socket listening onLocalAddr:LocalPort
.The
Listen
take the same list of arguments asIO::Socket::INET->new()
with some additions:-
SilenceT
-
Silence timeout. See
new()
for details. Accept
-
Contains the pointer to the external accept function provided by you.
When the new connection will be detected by listening TCP socket the new socket will be created by
IO::Socket::INET->accept()
. After that the externalAccept
function will be called with just one parameter: the ID for the new socket.External
Accept
have to returntrue
value otherwise new socket will be closed and connection will be rejected. MaxClients
-
The maximum number of simultaneous incoming connections.
If current number of children of this listening socket is bigger than
MaxClients
new connections are not accepted.'0'
mean 'do not accept new connections'. The default is '9999999999' which is quite close to unlimited. ClientsST
-
The silence timeout for children sockets. Default is the nest
SilenceT
.
-
Connect(%PARAMHASH);
-
The
Connect()
method create new socket connected toPeerAddr:PeerPort
.The
Connect()
take the same list of arguments asIO::Socket::INET->new()
with same additions asListen()
. The Proto key is required.Connect()
method returns theSocketID
, the symbolic name which have to be used for work with particular socket in nest usingGets()
,Puts()
,Recv()
andProperties()
methods. In case of problemsConnect()
returnsundef
value.$@
will contain a error message. - Important note
-
Listen
andConnect
are synchronous. So if connection establishing take a long time - for eaxmple because of slow DNS resolving - your program will be frozen for a long time. Gets($SocketID, [$MaxLength]);
-
For TCP sockets the
Gets
method returns a string received from corresponding socket. "String" means(.*\n)
.If data is available for reading but
"\n"
is not presented in first$MaxLength
bytes, the$MaxLength
bytes will be returned.For non-TCP sockets the
Gets
works with blocks of data read from socket by singleIO::Socket::INET->recv
call. It is necessary to provide correctPeerAddr
andPeerPort
. So, if"\n"
found in the block and length of string is no more than$MaxLength
, the string will be returned. If no"\n"
found in the block and block length is no more than$MaxLength
, the whole block will be returned. If string is too long or block is too big,$MaxLength
bytes will be returned.Default
$MaxLength
is socketBiffSize
.$MaxLength
forGets
have to be no more than32766
. It will be adjusted automaticaly otherwise.If no data available for reading,
Gets
returns empty string.If socket closed or
$SocketID
is invalidGets
returnsundef
.In list context method returns an array of 3 elements: [0] - string as in scalar context [1] - PeerAddr [2] - PeerPort
Note:
Gets
is not reading data from the socket but takes it from special buffer filled byIO
method with data read from socket during last call.If you did not read all the data available in buffer new data will be appended to the end of buffer.
Recv($SocketID, [$MaxLength]);
-
For TCP sockets the
Recv
method returns all data available from corresponding socket if data length is no more than$MaxLength
. Otherwise$MaxLength
bytes returned.For non-TCP sockets the
Recv
works with blocks of data read from socket by singleIO::Socket::INET->recv
call. It is necessary to provide correctPeerAddr
andPeerPort
. So, if block length is no more than$MaxLength
, the whole block will be returned. If block is too big,$MaxLength
bytes will be returned.Default
$MaxLength
is socketBiffSize
.If no data available for reading,
Recv
returns empty string.If socket is closed or
$SocketID
is invalidRecv
returnsundef
.In list context method returns an array of 3 elements: [0] - string as in scalar context [1] - PeerAddr [2] - PeerPort
Note:
Recv
is not reading data from the socket but takes it from special buffer filled byIO
method. Read($SocketID, [$MaxLength]);
-
This method is little bit eclectic but I found it's useful.
If string
"\n"
is presented in the buffer this method will act asGets
method. Otherwise it will act asRecv
.$MaxLength
forRead
have to be no more than32766
. It will be adjusted automaticaly otherwise. Puts($SocketID, $Data, $PeerAddr, $PeerPort);
-
The
Puts
method puts data to the corresponding socket outgoing buffer.$PeerAddr:$PeerPort
pair is the destination which$Data
must be sent. If not specified these fields will be taken from socket properties.$PeerAddr:$PeerPort
will be ignored on TCP sockets.If socket closed or
$SocketID
is invalidRecv
returnsundef
. Otherwise it returns 1.Note:
Puts
is not writing data directly to the socket but puts it to the special buffer which will be flushed to socket byIO
method during next call. Send($SocketID, $Data);
-
Just a synonym for
Puts
. PeerAddr($SocketID);
-
For TCP sockets the
PeerAddr
method returns the IP address which is socket connected to or empty string for listening sockets.For non-TCP sockets the
PeerAddr
method returns the IP address which was used for sending last time or IP address which is corresponding to data read by lastGets
orRecv
call.If socket closed or
$SocketID
is invalidPeerAddr
returnsundef
. PeerPort($SocketID);
-
For TCP sockets the
PeerPort
method returns the IP address which is socket connected to or empty string for listening sockets.undef
For non-TCP sockets the
PeerPort
method returns the port which was used for sending last time or port which is corresponding to data read by lastGets
orRecv
call.If socket closed or
$SocketID
is invalidPeerPort
returnsundef
. LocalAddr($SocketID);
-
The
LocalAddr
method returns the IP address for this end of the socket connection.If socket closed or
$SocketID
is invalidLocalAddr
returnsundef
. LocalPort($SocketID);
-
The
LocalPort
method returns the IP address for this end of the socket connection.If socket closed or
$SocketID
is invalidLocalPort
returnsundef
. Handle($SocketID);
-
The
Handle
method returns the handle to theIO::Socket::INET
object associated with$SocketID
orundef
if$SocketID
is invalid or socket closed. Properties($SocketID, [%PARAMHASH]);
-
The
Properties
method returns the hash in list context or pointer to the hash in scalar context. Hash itself is containing socket properties which are:-
Handle
-
The handle to the socket associated with
$SocketID
. Read-only. Input
-
The length of data in buffer waiting to be read by
Gets
orRecv
. Read-only. Output
-
The length of data in buffer waiting for sending to the socket. Read-only.
BytesIn
-
The number of bytes which was received from socket. Read-only.
BytesOut
-
The number of bytes which was sent out to socket. Read-only.
CTime
-
The socket creation time as was returned by
time()
. Read-only. ATime
-
The time when socket was sending or receiving data last time. Read-only.
PeerAddr
-
The value is the same as returned by
PeerAddr
method. Read-only. PeerPort
-
The value is the same as returned by
PeerPort
method. Read-only. LocalAddr
-
The value is the same as returned by
LocalAddr
method. Read-only. LocalPort
-
The value is the same as returned by
LocalPort
method. Read-only. SilenceT
-
The 'silence timeout'. After
SilenceT
seconds of inactivity the socket will be closed. Inactivity mean 'no data send or receive'.0
mean 'infinity'. ClientsST
-
Make sense for TCP listening sockets only. This is the 'silence timeout' for children (created by incoming connection accepting) sockets. See
Listen
for details. Clients
-
Make sense for TCP listening sockets only. Contains the number of child sockets active at the moment. Read-only.
MaxClients
-
Make sense for TCP listening sockets only. The maximum number of child sockets. See
Listen
for details. Accept
-
Make sense for TCP listening sockets only. The pointer to the external
Accept
function. SeeListen
for details. Parent
-
For sockets created automaticaly by accepting incoming TCP connection this field contain the
SocketID
of parent (listening) socket. For other socketsParent
contains empty string. Read-only. BuffSize
-
The size of buffer for
IO::Socket::INET->recv
function.
The following parameters could be changed if new value will be provided in the
%PARAMHASH
:-
SilenceT
BuffSize
MaxClients
ClientsST
ATime
Accept
It is useless to set
MaxClients
orClientsST
orAccept
for any sockets except TCP listening sockets
-
Close($SocketID);
-
Put the "close" request for the socket
$SocketID
. The actual removing will be done byIO
method during next call.Remember: it is important to call
Close
for all socket which have to be removed even they become to be unavailable because ofsend()
orrecv()
error. SafeStr($Str);
-
Just change all dangerous symbols (
\x00-\x1F
and\xFF
) in a string to their hexadecimal codes and returns the updated string. Nothing relative to sockets but can be very usefull for logging pourposes
EXPORT
SafeStr
AUTHOR
Daniel Podolsky, <tpaba@cpan.org>