in reply to Sock-Server and Sock-Client
Appologies for the VERY long post. I assume that you are running on a Win32 platform as you talk about an exe. You might have a look at running your server as a Win32 Service (Not for the faint hearted) but Re: Install a perl script as a Win NT/2000/XP service. should give you some ideas, or Re: kill a child / parent process (Service Skeleton) where you can get a kick start for the service stuff.
As far as the client connecting to the server, the server doing stuff with what it receives and exiting the client when a key is pressed there are many references to this type of thing you just need to scratch around a bit. If you have made the server into a Win32 Service all you have to do to stop the server is to Stop the Service.
Below is a simple example. I cant remember if I made any changes to the following code and so, have NOT tested it, but it should give to a good start.
Update:Added Service Installer code.
Server ...
#! 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 Clea +n 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); }
Client ...
#! perl.exe -w ###################################################################### +################## ## ## Client_Skeleton ## ###################################################################### +################## use strict; use Getopt::Long qw (GetOptions); use IO::Socket; #List of variables used in this program my (%opts, $VERSION,); $VERSION = "1.0"; #Set the options for GetOpt Getopt::Long::Configure( "pass_through", "no_ignore_case", "prefix_pat +tern=(-|\/)" ); #What to expect on the command line %opts = (); GetOptions (\%opts, 'help|h|?', 'port=s', 'server=s', 'msg=s', ); #Set help option on if the correct parameters are not inserted $opts{help} = 1 unless (defined $opts{port} && defined $opts{server} & +& defined $opts{msg}); if( $opts{help} ) { Syntax(); exit(); } &Transmit_Msg($opts{msg}); ###################################################################### +################## ## ## SUB ROUTINES ## ###################################################################### +################## #Create socket connection and send message to server. sub Transmit_Msg($msg) { my $MAXLEN = 1024; my $msg = shift; my $sock = IO::Socket::INET->new( Proto => 'tcp', PeerPort => $opts{port}, PeerAddr => $opts{server}, ) or die "Could Not Connect to Server Socket(Check Ser +vice is Running): $!\n"; print $sock "$msg\n"; # &Notify("Sent $msg"); close ($sock); } #Print out the proper syntax if some parameters are missing. sub Syntax { my( $Script ) = ( $0 =~ m#([^\\/]+)$# ); my $Scriptdetails = "$Script - Version: $VERSION"; my $Line = "-" x length( $Scriptdetails ); print << "EOT"; $Scriptdetails $Line This program will send a TCP message to the server. You Must add Port + and Server Address as well as the Message to send in Quotes Syntax: $0 [-p|--port=<port number>] [-s|--server=<Server Address>] [-m|-- +msg=<"Message To Send"[-h|--help|?] EOT }
You are going to need an installer for the service..
-----#X-CallInstall use strict; use warnings; use Win32; use Win32::Daemon; use Getopt::Long; my ($VERSION, %Config); $VERSION = "1.0"; %Config = (timeout_value => 2, log_file => join( "", Win32::GetFullPathName( $0 ) ), ); $Config{log_file} =~ s/[^.]*?$/log/; Getopt::Long::Configure( "prefix_pattern=(-|\/)" ); my $Result = GetOptions( \%Config, qw( install|i remove|r account_id|user=s account_password|pass=s help|?|h ) ); $Config{help} = 1 if( ! $Result || scalar @ARGV ); if( $Config{install}) { &Install(); exit(); } elsif ( $Config{remove}) { &Remove(); exit(); } elsif( $Config{help}) { &Syntax(); exit(); } #Configuration for Service sub GetServiceConfig { my $script_path = join("",Win32::GetFullPathName($0)); my %hash = ( name => 'Skeleton Socket Server', display => 'Skeleton Socket Server', description => "Skeleton Socket Server v$VERSION", path => $^X, user => $Config{account_id}, password => $Config{account_password}, parameters => "C:\\Pathtoscript\\skelserv.pl", ); return(\%hash); } #Install Service sub Install { my $svc_cfg = &GetServiceConfig(); if (Win32::Daemon::CreateService($svc_cfg)) { print "The $svc_cfg->{display} was Successfully installed.\n"; } else { print "Failed to Install $svc_cfg->{display} service.\nError: +" . GetError() . "\n"; } } #Remove Service sub Remove { my $service_config = GetServiceConfig(); if( Win32::Daemon::DeleteService( $service_config->{name} ) ) { print "The $service_config->{display} was successfully removed +.\n"; } else { print "Failed to remove the $service_config->{display} service +.\nError: " . GetError() . "\n"; } } #Display if no Command Line Arguments Found! sub Syntax { print << "EOT"; A Win32 service that Create a Socket to listen on for X-Transp +ort Messages. Syntax: [-l <Path>] [-t <Time>] [-remove][-install [-user <User> -pass + <Pwd}]] -install........Installs this script as a Win32 service. Any additional parameters passed in will set be wh +at the script uses when running as a service. -remove.........Removes this script as a Win32 service. Examples +: perl $0 -install perl $0 -install -user Domain\\User -pass UserPassword -l c:\\moni +tor.log -d perl $0 -remove EOT } #Display Errors sub GetError { return( Win32::FormatMessage( Win32::Daemon::GetLastError() ) ); }
|
|---|