#! perl.exe ######################################################################################## ## ## Server Service ## ######################################################################################## use Win32; use Win32::Daemon; #Manipulate the Win32 Service use Socket; #Create and Manipulate Sockets use IO::Socket; #Create and Manipulate Sockets use IO::Select; #Use for Non-Blocking Sockets use strict; use warnings; ######################################################################################## #Service Variables my ($Result, $PrevState, $State); #Socket Variables my ($remote, $port, $sock, @client_list, $sel); #Misc Variables my ($VERSION, $logfile, $timeout); ######################################################################################## $VERSION = "1.0"; $logfile = "c:/Logs/SockSrv.log"; $port = 54321; $timeout = 2; #Open Log File if (open( LOG, ">>$logfile" ) ) { my $TempSelect = select( LOG ); $| = 1; select( $TempSelect ); print LOG "\n# Date: " . localtime() . "\n================================\n"; } if( ! Win32::Daemon::StartService()) { if( fileno( LOG ) ) { &Update_Log("Failed to start this script as a Win32 service.\n"); &Update_Log("Error: " . GetError()); close($sock); close( LOG ); } exit(); } $PrevState = "SERVICE_STARTING"; while( SERVICE_STOPPED != ( $State = Win32::Daemon::State() ) ) { if( SERVICE_START_PENDING == $State ) { # Initialization code Win32::Daemon::State( SERVICE_RUNNING ); @client_list = (); &Create_Socket(); &Debug_Log("DEBUG - Service is Running\n"); $PrevState = SERVICE_RUNNING; } elsif( SERVICE_PAUSE_PENDING == $State ) { # "Pausing..."; Win32::Daemon::State( SERVICE_PAUSED ); &Debug_Log("DEBUG - Service is Paused\n"); #Clean Up Memory and Sockets if ($remote) { close($remote); } close($sock); &Debug_Log("DEBUG - Socket Closed\n"); $PrevState = SERVICE_PAUSED; next; } elsif( SERVICE_CONTINUE_PENDING == $State ) { # "Resuming..."; Win32::Daemon::State( SERVICE_RUNNING ); &Debug_Log("DEBUG - Service Continue\n"); #Setup Socket &Create_Socket(); &Debug_Log("DEBUG - Socket RE-Created\n"); $PrevState = SERVICE_RUNNING; next; } elsif ( SERVICE_STOP_PENDING == $State ) { # "Stopping..."; Win32::Daemon::State( SERVICE_STOPPED ); $PrevState = SERVICE_STOPPED; #Clean Up Memory and Sockets if ($remote) { close($remote); } close($sock); #Backup ExistCalls into ExistCalls File &Debug_Log("DEBUG - Socket Closed\n"); &Update_Log("Service is Stoped\n"); next; } elsif( SERVICE_RUNNING == $State ) { # The service is running as normal... $PrevState = SERVICE_RUNNING; my $read_buffer = 1024; while (@client_list = $sel->can_read(1)) { foreach $remote(@client_list) { if ($remote == $sock) { my $new_remote = $sock->accept; $sel->add($new_remote) if ($new_remote); &Update_Log("Accepted new Client\n"); } else { my $msg = <$remote>; chomp($msg); #Look at what we received from the Client &Update_Log("\nRECEIVED FROM CLIENT - $msg\n"); $sel->remove($remote) or Debug_Log("Could Not Clean Up the Select:$!\n"); close($remote); } } } } else { # We have some unknown state... # reset it back to what we last knew the state to be... Win32::Daemon::State( $PrevState ); sleep( $timeout ); } } #Stop the Service Win32::Daemon::StopService(); if( fileno( LOG ) ) { &Update_Log("================================\n"); &Update_Log("Service Stopped.\n" . localtime()); close LOG; } ######################################################################################## ## ## SUB ROUTINES ## ######################################################################################## #Create a Socket to listen on sub Create_Socket { &Update_Log("Socket Created"); my $max_length = 1024; my $max_clients = 10; $sock = IO::Socket::INET->new( LocalPort => $port, Proto => 'tcp', Listen => $max_clients ) or die &Debug_Log("...Failed\nCould Not Create Socket: $@\n"); $sel = IO::Select->new($sock); &Update_Log(" ... Successful\n"); &Update_Log("Awaiting messages on: $port\n"); return(0); } #Update Log file sub Update_Log { if (! $_[0]) { return (0); } print LOG "$_[0]"; return(0); }