NAME
Net::Socket::NonBlock - Perl extension for easy creation multi-socket single-thread application, especially non-forking TCP servers
Version 0.15
SYNOPSIS
# TCP port forwarder with logging
# Works on Win32!
use strict;
use Net::Socket::NonBlock;
$|++;
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::Nest->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";
$SrvSock->Puts($Str);
};
if (!defined($Str))
{
$Pstr .= " $ClientID CLIENT closed\n";
$SockNest->Close($ClnSock); # Old-style method call
$SrvSock->Close(); # OO-style method call
delete($ConPool{$ClnSock});
next;
};
while(($Str = $SrvSock->Read()) && length($Str))
{
$Pstr .= " $ClientID From SERVER ".SafeStr($Str)."\n";
$SockNest->Puts($ClnSock, $Str);
};
if (!defined($Str))
{
$Pstr .= " $ClientID SERVER closed\n";
$SockNest->Close($ClnSock);
$SrvSock->Close();
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";
$ClnSock->Close();
delete($ConPool{$ClnSock});
return;
};
return 1;
};
sub SafeStr
{
my $Str = shift
or return '!UNDEF!';
$Str =~ s{ ([\x00-\x1f\xff\\]) } { sprintf("\\x%2.2X", ord($1)) }gsex;
return $Str;
};
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 module contains two packages: Net::Socket::NonBlock and Net::Socket::NonBlock::Nest.
The Net::Socket::NonBlock::Nest methods
new(%PARAMHASH);-
The
newmethod creates theNet::Socket::NonBlock::Nestobject and returns a handle to it. This handle is then used to call the methods below.The
Net::Socket::NonBlock::Nestobject itself is the table contains socket handlers, InOut buffers, etc.Net::Socket::NonBlock::Nestobject also contain aIO::Selectobject which is common for all sockets generated from this nest.To create new socket you should use
ListenorConnectmethods (see below). Also, socket could be created automatically during TCP connection accept procedure inside ofNet::Socket::NonBlock::Nest::IO()method.The %PARAMHASH could contain the following keys:
SelectT-
SelectTis the timeout forIO::Select->can_readandIO::Select->can_writefunction. See IO::Select for details. Default is 0.1 second. SilenceT-
If no data was transferred trough socket for
SilenceTseconds the socket will be closed. Default is '0'. IfSilenceT = 0socket will nether been closed by timeout.This value is the default for all sockets created by
ListenorConnectmethod if another value will not be provided inListenorConnectparameters. Also, you will be able to change this parameter for any socket in nest usingPropertiesmethod (see below). BuffSize-
The size of buffer for
IO::Socket::INET->recvfunction (see IO::Socket::INET). Default isPOSIX::BUFSIZ(seePOSIX).This is default for all sockets which will be created and could be overwritten by
Listen,ConnectorPropertiesmethods. debug-
If true, additional debug info will be printed during program execution.
newNest();-
Just a synonym for
Net::Socket::NonBlock::Nest->new() Properties([%PARAMHASH]);-
The
Propertiesmethod returns the hash in list context or pointer to the hash in scalar context. Hash itself is containing nest properties which are:Sockets-
The number of sockets currently active on this nest.
SelectTSilenceTBuffSizedebug-
See
new()for detailed explanation.
The following parameters could be changed if new value will be provided in the
%PARAMHASH:SelectTSilenceTBuffSizedebug
NestProperties();-
Just a synonym for
Net::Socket::NonBlock::Nest::Properties() IO([$Errors]);-
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.
$Errorscould be a reference to the array. After theIO()call this array will conatin the messages for errors ocured during the call. Note:IO()cleans this array every time.Net::Socket::NonBlock::Nest::IO()returns a number ofrecv()oraccept()operations or'0 but true'if none. SelectT([$Timeout]);-
If
$Timeoutis not specified theSelectTmethod returns a current value ofSelectT.If
$Timeoutis specified theSelectTmethod set theSelectTto the provided value and returns a previous one.This method is provided for hysterical raisin. Please use the
Propertiesmethod instead. Listen(%PARAMHASH);-
The
Listenmethod create new socket listening onLocalAddr:LocalPort.The
Listentake 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
Net::Socket::NonBlockobject will be created. After that the externalAcceptfunction will be called with just one parameter: the newNet::Socket::NonBlockobject.External
Accepthave to returntruevalue 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
MaxClientsnew 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. Broadcast-
If
Broadcastis defined and 'true' thesockopt(SO_BROADCAST, 1)will be called for newely created socket to make it ready to send broadcast packets.If
Broadcastis defined but 'false' thesockopt(SO_BROADCAST, 0)will be called for newely created socket.See IO::Socket for more information about
sockoptandSO_BROADCAST. DiscEmpty-
Discard empty datagrams. Default is do not discard them.
Useless on TCP sockets.
Listen()method returns aNet::Socket::NonBlockobject. In case of problemsListen()returns anundefvalue.$@will contain an error message. 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 aNet::Socket::NonBlockobject. In case of problemsConnect()returns anundefvalue.$@will contain an error message. - Important note
-
ListenandConnectare synchronous. So if connection establishing take a long time - for example because of slow DNS resolving - your program will be frozen for a long time.
The Net::Socket::NonBlock methods
- new() and newNest()
-
Just the synonyms for
Net::Socket::NonBlock::Nest->new()Note: to create new
Net::Socket::NonBlockobject you should useNet::Socket::NonBlock::Nest->new()orNet::Socket::NonBlock::Nest->Connect()methods Gets([$BufLength]);-
For TCP sockets the
Getsmethod returns a string received from corresponding socket. "String" means(.*\n).If data is available for reading but
"\n"is not presented in first$BufLengthbytes, the$BufLengthbytes will be returned.For non-TCP sockets the
Getsworks with blocks of data read from socket by singleIO::Socket::INET->recvcall. It is necessary to provide correctPeerAddrandPeerPort. So, if"\n"found in the block and length of string is no more than$BufLength, the string will be returned. If no"\n"found in the block and block length is no more than$BufLength, the whole block will be returned. If string is too long or block is too big,$BufLengthbytes will be returned.Default
$BufLengthis socketBiffSize.Value of
$BufLengthshould not be bigger thanBiffSizeor value32766what is less. It will be adjusted automaticaly otherwise.If no data available for reading,
Getsreturns empty string.If socket closed
Getsreturns anundefvalue.$@will contain an error message.In list context method returns an array of 3 elements: [0] - string as in scalar context [1] - PeerAddr [2] - PeerPort
Note:
Getsis not reading data from the socket but takes it from special buffer filled byNet::Socket::NonBlock::Nest::IO()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([$BufLength]);-
For TCP sockets the
Recvmethod returns all data available from corresponding socket if data length is no more than$BufLength. Otherwise$BufLengthbytes returned.For non-TCP sockets the
Recvworks with blocks of data read from socket by singleIO::Socket::INET->recvcall. It is necessary to provide correctPeerAddrandPeerPort. So, if block length is no more than$BufLength, the whole block will be returned. If block is too big,$BufLengthbytes will be returned.Default
$BufLengthis socketBiffSize.If no data available for reading,
Recvreturns empty string.If socket is closed
Recvreturns anundefvalue.$@will contain an error message.In list context method returns an array of 3 elements: [0] - string as in scalar context [1] - PeerAddr [2] - PeerPort
Note:
Recvis not reading data from the socket but takes it from special buffer filled byNet::Socket::NonBlock::Nest::IO()method. Read([$BufLength]);-
This method is little bit eclectic but I found it useful.
If string
"\n"is presented in the buffer this method will act asGetsmethod. Otherwise it will act asRecv.Default
$BufLengthis socketBiffSize.Value of
$BufLengthshould not be bigger thanBiffSizeor value32766what is less. It will be adjusted automaticaly otherwise.If socket is closed
Recvreturns anundefvalue.$@will contain an error message. Puts($Data [, $PeerAddr, $PeerPort]);-
The
Putsmethod puts data to the corresponding socket outgoing buffer.$PeerAddr:$PeerPortpair is the destination which$Datamust be sent. If not specified these fields will be taken from socket properties.$PeerAddr:$PeerPortwill be ignored on TCP sockets.$Datacould be a reference to anARRAY. In this case the string to send will be constructed byjoin('', @{$Data})operation.If socket is closed
Recvreturns anundefvalue.$@will contain an error message. Otherwise it returns 1.Note:
Putsis not writing data directly to the socket but puts it to the special buffer which will be flushed to socket byNet::Socket::NonBlock::Nest::IO()method during next call.Size of output buffer is not monitored automaticaly. It is definitely good idea to do it yourself to prevent memory overuse. See
Properties()(Output) for details Send();-
Just a synonym for
Puts(). PeerAddr();-
For TCP sockets the
PeerAddrmethod returns the IP address which is socket connected to or empty string for listening sockets.For non-TCP sockets the
PeerAddrmethod returns the IP address which was used for sending last time or IP address which is corresponding to data read by lastGetsorRecvcall.If socket is closed
Recvreturns anundefvalue.$@will contain an error message. PeerPort();-
For TCP sockets the
PeerPortmethod returns the IP address which is socket connected to or empty string for listening sockets.undefFor non-TCP sockets the
PeerPortmethod returns the port which was used for sending last time or port which is corresponding to data read by lastGetsorRecvcall.If socket is closed
Recvreturns anundefvalue.$@will contain an error message. LocalAddr();-
The
LocalAddrmethod returns the IP address for this end of the socket connection.If socket closed
LocalAddrreturnsundef. LocalPort();-
The
LocalPortmethod returns the IP address for this end of the socket connection.If socket is closed
Recvreturns anundefvalue.$@will contain an error message. Handle();-
The
Handlemethod returns the handle to theIO::Socket::INETobject associated withNet::Socket::NonBlockobject orundefif socket closed. Properties([%PARAMHASH]);-
The
Propertiesmethod 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
Net::Socket::NonBlockobject. Read-only. Input-
The length of data in buffer waiting to be read by
GetsorRecv. 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
PeerAddrmethod. Read-only. PeerPort-
The value is the same as returned by
PeerPortmethod. Read-only. LocalAddr-
The value is the same as returned by
LocalAddrmethod. Read-only. LocalPort-
The value is the same as returned by
LocalPortmethod. Read-only. SilenceT-
The 'silence timeout'. After
SilenceTseconds of inactivity the socket will be closed. Inactivity mean 'no data send or receive'.0mean 'infinity'. ClientsST-
Make sense for TCP listening sockets only. This is the 'silence timeout' for children (created by incoming connection accepting) sockets. See
Listenfor 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
Listenfor details. Accept-
Make sense for TCP listening sockets only. The pointer to the external
Acceptfunction. SeeListenfor details. Parent-
For sockets created automaticaly by accepting incoming TCP connection this field contain the
SocketIDof parent (listening) socket. For other socketsParentcontains empty string. Read-only. BuffSize-
The size of buffer for
IO::Socket::INET->recvfunction. Error-
The message for last error ocured on this socket during last
Net::Socket::NonBlock::Nest::IO()call. Or just an empty string if no errors. Broadcast-
The status of
SO_BROADCASToption of the socket. DiscEmpty-
The status of
'DiscEmpty'flag.
The following parameters could be changed if new value is provided in the
%PARAMHASH:-
SilenceTBuffSizeMaxClientsClientsSTATimeAcceptBroadcastDiscEmpty
It is useless to set
MaxClientsorClientsSTorAcceptfor any sockets except TCP listening socketsIf socket is closed
Propertiesreturns anundefvalue.$@will contain an error message.
Close([$Flush [, $Timeout]]);-
Put the "close" request for the
Net::Socket::NonBlockobject. The actual removing will be done byNet::Socket::NonBlock::Nest::IO()method during next call.$Flushis a boolean parameter which tellsNet::Socket::NonBlock::Nest::IO()method to flush the output buffer before close the socket.$Timeoutis an amount of seconds after that the socket will be closed even it still have some data in the output buffer.Remember: it is important to call
Closefor all socket which have to be removed even they become to be unavailable because ofsend()orrecv()error or silence timeout. close()-
Just a synonym for
Close()
Note:
For historical reason the methods Properties(), Gets(), Read(), Recv(), Puts(), Send(), PeerAddr(), PeerPort(), LocalAddr(), LocalPort(), Handle() and Close() could be called in form
$SocketNest->methodName(SocketID, methodParams)
SocketID could be the reference to the Net::Socket::NonBlock object or this reference converted to the string.
This form could be usefull if you have the Net::Socket::NonBlock object reference only as a string, for example if you are using it as a hash key.
EXPORT
None.
AUTHOR
Daniel Podolsky, <tpaba@cpan.org>