#!/usr/bin/perl
use warnings;
use strict;
use IO::Socket;
use threads;
use threads::shared;
$|++;
print "$$ Server started\n";; # do a "top -p -H $$" to monitor server threads
my $buf2;
my $SyncID;
my $SyncHeader;
my $UnitID;
our @clients : shared;
@clients = ();
our $k;
our $m;
our $n;
our $p;
our $dup=0;
our $sel_cli2;
my @Mdevices;
my $ref;
my $peerC = 1;
####
my $server = new IO::Socket::INET(
Timeout => 500,
Proto => "tcp",
LocalPort => 8000,
Reuse => 1,
Listen => 5
);
my $num_of_client = -1;
while (1) {
my $client;
do {
$client = $server->accept;
} until ( defined($client) );
my $peerhost = $client->peerhost();
$peerC = $peerhost;
if ($peerC ne '127.0.0.1')
{
my $template = 'vvV';
read $client, my $sync_packet,8
or die "Couldn't read from client: $!";
($SyncHeader,$SyncID,$UnitID) = unpack $template, $sync_packet;
print "accepted a client $client, $UnitID, $peerhost, id = ", ++$num_of_client, "\n";
} else {
$UnitID = 888;
print "accepted a client $client, $peerhost, id = ", ++$num_of_client, "\n";
}
my $fileno = fileno $client;
push (@clients, $fileno);
for ($k=0; $k<=$#Mdevices; $k++)
{
if ($Mdevices[$k][0] eq $UnitID) # searching existing UnitID in Array
{
$dup =1;
print "Duplicate found $Mdevices[$k][0] |";
$Mdevices[$k][1] = $fileno; # update existing UnitID with new fileno
}
}
if ($dup eq 1)
{
print "NO changes |";
$dup = 0;
} else {
for ($n=0; $n<=$#Mdevices; $n++) # chech if exist some entry with old fileno, should be deleted
{
if ($Mdevices[$n][1] eq $fileno)
{
print "deleting |";
$Mdevices[$n][1] = 0; # set old entry's fileno to 0 to not interfere.
}
}
push (@Mdevices, [$UnitID, $fileno]); # add new device with fileno to array
}
use Data::Dumper;
print Dumper(\@Mdevices);
#spawn a thread here for each client
my $thr = threads->new( \&processit, $client, $fileno, $peerhost )->detach();
}
####
sub processit {
my ($lclient,$lfileno,$lpeer) = @_; #local client
my $sel_cli_id = $num_of_client;
if($lclient->connected){
while(<$lclient>)
{
if ($peerC eq '127.0.0.1') # tcp client from localhost is used just to send commands to other connected clients
{
my(@comm) = split(/:/, $_);
my $sel_clix = $comm[0];
my $commandC = $comm[1];
for ($p=0; $p<=$#Mdevices; $p++)
{
if ($Mdevices[$p][0] eq $sel_clix)
{
$sel_cli2 = $Mdevices[$p][1];
}
}
foreach my $fn ($sel_cli2)
{
if ($sel_cli2)
{
open my $fh, ">&=$fn" or warn $! and die;
print "\n $lclient $sel_cli2 Command sent to: $sel_clix Command: $commandC";
print $fh "$commandC\n"
} else {
print "\n $lclient Device: $sel_clix NOT avaiable to receive command\n";
}
}
} else {
print "COMMAND RESPONCE: $_";
}
}
}
#close filehandle before detached thread dies out
close( $lclient);
#remove multi-echo-clients from echo list
@clients = grep {$_ !~ $lfileno} @clients;
}