#!/usr/bin/perl use strict; use warnings; use IO::Socket::INET; use threads; #use Net::MQTT::Simple; use POSIX qw(strftime); #use Sys::Syslog qw(:DEFAULT :standard :macros); use IO::Select; my $mqtt; my $client; my $ident='tcp-mqtt_server'; my $logopt='ndelay'; my $facility='LOG_USER'; my $th_id; my $topic; my $value; my $holdtime=20; my $timeout=5; my @wants=qw/TEMP VBAT VLIN/; sub Main { my $sel_read = IO::Select->new(); my $conn=0; # $mqtt = Net::MQTT::Simple->new("localhost:1883"); # openlog($ident, $logopt, $facility); # don't forget this # flush after every write $| = 1; my ( $socket, $client_socket ); # Bind to listening address and port $socket = new IO::Socket::INET ( LocalHost => '0.0.0.0', LocalPort => '1001', Proto => 'tcp', Listen => 5, Reuse => 1 ) or die "Could not open socket: ".$!."\n"; $sel_read-> add($socket); print "SERVER Waiting for client connections...\n"; # syslog(LOG_INFO,"tcp-mqtt server starting"); my %clients; superloop:while(1) { my ($rd_ptr,$wr_ptr,$er_ptr)=IO::Select->select($sel_read,undef,undef,$timeout); print "superloop clients ",scalar((keys(%clients))),"\n"; for my $client_socket( sort { $clients{$a}{topen} <=> $clients{$b}{topen}} keys(%clients) ) { my $pid=$clients{$client_socket}{peer_address}.':'.$clients{$client_socket}{peer_port}; print ' ',$pid,' ',$clients{$client_socket}{copen},"\n"; } for my $fh (@$rd_ptr) { if ($fh == $socket) { $conn++; # Waiting for new client connection. $client_socket = $socket->accept(); # Push new client connection to it's own thread $clients {$client_socket}={ socket =>$client_socket ,thread =>threads->create( \&clientHandler, $client_socket ) ,peer_address =>$client_socket->peerhost() ,peer_port =>$client_socket->peerport() ,local_port =>$client_socket->sockport() ,topen =>time }; $clients{$client_socket}{copen}=strftime "%a %b %e %H:%M:%S %Y", localtime $clients{$client_socket}{topen}; my $started=$clients{$client_socket}{thread}; my $nclients=scalar((keys(%clients))); my $pid=$clients{$client_socket}{peer_address}.':'.$clients{$client_socket}{peer_port}; print "Connection $conn $pid clients $nclients\n" } # socket } # fh my @opened=keys(%clients); my @eofable=(); for my $open ( @opened ) { my $thread=$clients{$open}{thread}; if( $thread->is_joinable() ) { $thread->join(); my $pid=$clients{$open}{peer_address}.':'.$clients{$open}{peer_port}; print "Joined $pid\n"; push @eofable,$open; } # joinable } #opened for my $open ( @eofable ) { # my $socket=$clients{$open}{socket}; # magic lost in stringified key # close($socket); my $pid=$clients{$open}{peer_address}.':'.$clients{$open}{peer_port}; delete $clients{$open}; # destroys socket and thread objects; my $nclients=scalar((keys(%clients))); print "Cleaned $pid clients $nclients\n"; } # eofable } # superloop $socket->close(); return 1; } sub clientHandler { my ($client_socket) = @_; my %user = (); $user{peer_address} = $client_socket->peerhost(); $user{peer_port} = $client_socket->peerport(); $user{local_port} = $client_socket->sockport(); $th_id = threads->tid(); my $isopen=1; my $pid=$user{peer_address}.":".$user{peer_port}; print "Client ".$user{peer_address}.":".$user{peer_port}.":".$user{local_port}."\n"; # syslog(LOG_INFO,"Client $user{peer_address}:$user{peer_port}:$user{local_port}:$th_id is connected"); eval{ while ($isopen) { my $datestring = strftime "%a %b %e %H:%M:%S %Y", localtime; print "$datestring\n"; print $client_socket "\n"; for my $want (@wants) { $isopen=0; print $client_socket $want,"\n"; while( my $buffer = <$client_socket> ) { $isopen=1; print $pid,' ',$buffer; my $value = substr $buffer, 0,-2; # $mqtt->retain("minimon/VLIN" => $buffer); # syslog(LOG_INFO,"VLIN: $buffer"); last; } last unless ($isopen); } # want sleep($holdtime) if ($isopen); } # isopen }; if($@){ print "tcp-mqtt exception:$@->getErrorMessage()"; # syslog(LOG_INFO,"tcp-mqtt exception:$@->getErrorMessage()"); } $client_socket->shutdown(2); #$client_socket->close(); print "Client exit from ".$user{peer_address}.":".$user{peer_port}."\n"; # Client has exited so thread should exit too threads->exit(); } # Start the Main loop Main();