Perl Socket Conditional doesn't work - perl

I'm trying to create a server and client wherein the server returns a diferent message to the client according to what client sends. If the client makes the connection but sends nothing, the server will return message 1 and in case the client sends some data, the server will return message 2. But this doesn't work, the client stays waiting the data and nothing prints.
Client:
use IO::Socket;
my $sock = new IO::Socket::INET (
PeerAddr => '10.1.1.28',
PeerPort => '7070',
Proto => 'tcp' );
if (#ARGV != "") {
print $sock "$ARGV[0] $ARGV[1]";
} else {
$data = <$sock>;
print $data;
}
$sock->close;
Server
use IO::Socket;
my $sock = new IO::Socket::INET (
LocalHost => '10.1.1.28',
LocalPort => '7070',
Proto => 'tcp',
Listen => '1',
);
while(1) {
my $new_sock = $sock->accept();
if (<$new_sock> ne "") {
print $new_sock "conection with parameters";
} else {
print $new_sock "default message";
};

Need to chomp
use IO::Socket;
use Data::Dumper;
my $sock = new IO::Socket::INET(
LocalPort => '7070',
Proto => 'tcp',
Listen => '1',
);
while (1) {
my $new_sock = $sock->accept();
my $in = <$new_sock>;
chomp($in);
if ( $in ne "" ) {
print Dumper($in);
print $new_sock "conection with parameters";
}
else {
print $new_sock "default message";
}
}

Related

Sock Server and Client

I have the following Socks Server
my $socks_server = IO::Socket::Socks->new(
ProxyAddr => "localhost",
ProxyPort => 8000,
Listen => 1,
) or die "socket error";
while(1) {
my $client = $socks_server->accept();
print $client;
unless ($client) {
print "ERROR:";
next;
}
}
and the following Socks Client
use strict;
use warnings;
use IO::Socket::Socks;
my $socks_client = IO::Socket::Socks->new(
ProxyAddr => "localhost",
ProxyPort => "8000",
) or die $SOCKS_ERROR;
print $socks_client "foo\n";
$socks_client->close();
the Socks client print "foo\n" , how can I let the Socks Server print it to the console when its received?
Following code is provided for demonstration purpose only, authentication is turned off for simplicity.
The code is based on documetation for IO::Socket::Socks
Code for server.pl
use strict;
use warnings;
use feature 'say';
use IO::Socket::Socks ':constants';
my $SOCKS_ERROR = 'Error: SOCKS';
my $socks_server = IO::Socket::Socks->new(
ProxyAddr => "localhost",
ProxyPort => 8000,
Listen => 1,
UserAuth => \&auth,
RequireAuth => 0
) or die $SOCKS_ERROR;
while(1) {
my $client = $socks_server->accept();
unless ($client) {
print "ERROR: $SOCKS_ERROR\n";
next;
}
my $command = $client->command();
if ($command->[0] == CMD_CONNECT) {
# Handle the CONNECT
$client->command_reply(REPLY_SUCCESS, 'localhost', 8000);
}
print while <$client>;
$client->close();
}
sub auth {
my ($user, $pass) = #_;
return 1 if $user eq "foo" && $pass eq "bar";
return 0;
}
Code for client.pl
use strict;
use warnings;
use feature 'say';
use IO::Socket::Socks;
my $socks_client = IO::Socket::Socks->new(
ProxyAddr => "localhost",
ProxyPort => "8000",
ConnectAddr => "localhost",
ConnectPort => "8022",
) or die $SOCKS_ERROR;
print $socks_client $_ for <DATA>;
$socks_client->close();
__DATA__
-----------------------------------------------
This a test message sent from remote client for
SOCKS demonstration code.
Enjoy your day.
Output on server.pl side
C:\....\examples\socks_server.pl
-----------------------------------------------
This a test message sent from remote client for
SOCKS demonstration code.
Enjoy your day.
Output on client.pl side
C:\...\examples\socks_client.pl
C:\...>

Using IO::Socket::IP with Mojo::IOLoop

I am trying to achieve what these lines of code do synchronously, but asynchronously via Mojo::IOLoop and Mojo::Promises:
my $address = '192.168.1.240';
my $sock = IO::Socket::IP->new(PeerAddr => $address,
PeerPort => '9999',
Proto => 'tcp');
$sock->send($on);
my $data;
$sock->recv($data, 2048);
print $data;
This is used to communicate with a smartplug, and a promise-based interface would allow me to abstract out things, so that different plugs (some communicating via HTTP, some via TCP) could be handled in the same way.
Right now I've achieved the result by doing this
sub talk_to_plug_p {
my ($addr, $command) = #_;
my $promise = Mojo::Promise->new;
my $port = 9999;
my $sock = IO::Socket::IP->new(PeerAddr => $addr,
PeerPort => $port,
Proto => 'tcp');
return $promise->reject("Could not open socket on $addr at port $port") unless $sock;
my $id = Mojo::IOLoop->client({ handle => $sock } => sub {
my ($loop, $err, $stream) = #_;
$stream->on(read => sub {
my ($stream, $bytes) = #_;
# -------------------
# THIS LOOKS BAD
# -------------------
remove_id($loop);
$promise->resolve($bytes);
});
$stream->on(error => sub {
my $err = shift;
$promise->reject($err);
});
$stream->write($command);
});
sub remove_id { shift->remove($id) };
return $promise;
}
talk_to_plug_p('192.168.1.240', $on)->then(sub { print #_ })->catch(sub { print shift });
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
Now this works but it kind of looks wrong - especially the remove_id part, and I imagine there must eb a better way than this. I just could not find it.
What would be a cleaner way? i.e.: one that closes the client when bytes have been read, or where I can explicitly close the connection or something similar.

Perl: Printing through socket

I'm trying to script battleship with perl, which can be played over the network.
The problem is that i'm just able to print on the same console, but not on other consoles through the socket.
Client:
$socket = new IO::Socket::INET(
PeerHost => '127.0.0.1',
PeerPort => '5005',
Protocol => 'tcp'
) or die "Socket konnte nicht erstellt werden!\n$!\n";
print "Client kommuniziert auf Port 5005\n";
while ( $eing ne ".\n" ) {
$eing = <> ;
print $socket "$eing";
}
Server:
$socket = new IO::Socket::INET(
LocalHost => '127.0.0.1',
LocalPort => '5005',
Protocol => 'tcp',
Listen => 5,
Reuse => 1
) or die "Socket konnte nicht erstellt werden!\n$!\n";
while ( 1 ) {
$client_socket = $socket -> accept();
$peeraddress = $client_socket -> peerhost();
$peerport = $client_socket -> peerport();
$eing = "";
while ( $eing ne ".\n" ) {
print "while";
&ausgabe;
}
}
sub ausgabe {
foreach $crt_board (#board2) {
foreach $spalte (#$crt_board) {
print $client_socket "$spalte ";
}
print $client_socket "\n";
}
}
The result should be an board which looks like this.
1 2 3 4 5
1 ? ? ? ? ?
2 ? ? ? ? ?
3 ? ? ? ? ?
4 ? ? ? ? ?
5 ? ? ? ? ?
You need to read from a socket if you want transfer data from server to client, or vice versa. Do always use strict (and warnings). The following will get you started:
Client:
use strict;
use IO::Socket::INET;
my $socket = new IO::Socket::INET(
PeerHost => '127.0.0.1',
PeerPort => '5005',
Protocol => 'tcp'
) or die "Socket konnte nicht erstellt werden!\n$!\n";
print "Client kommuniziert auf Port 5005\n";
while ( 1 ) {
my $data;
$socket->recv($data, 64);
print $data;
last if $data =~ m#\.\n#;
}
Server:
use strict;
use IO::Socket::INET;
my $socket = new IO::Socket::INET(
LocalHost => '127.0.0.1',
LocalPort => '5005',
Protocol => 'tcp',
Listen => 5,
Reuse => 1
) or die "Socket konnte nicht erstellt werden!\n$!\n";
while ( my $client_socket = $socket -> accept() ) {
my $peeraddress = $client_socket -> peerhost();
my $peerport = $client_socket -> peerport();
ausgabe($client_socket);
}
sub ausgabe {
my $client_socket = shift;
my #board2 = ([" ", 1,2,3],[1,"?","?","?"],
[2,"?","?","?"], [3,"?","?","?"]);
foreach my $crt_board (#board2) {
foreach my $spalte (#$crt_board) {
$client_socket->send("$spalte ");
}
$client_socket->send("\n");
}
$client_socket->send(".\n");
}

Can't figure out how to fix this script in perl

I'm running this script in perl and correctly putting in the id and port. however, I keep getting "scalar found where operator expected at line 16 near"'skype://1024,'$ARGV"
#!usr/perl/bin
use LWP::UserAgent;
system("color a");
system("title Skype <<");
system("cls");
if(!$ARGV[0]||!$ARGV[1]) {
print q {
Usage : perl skype.pl [userid] [port=1024,80,433]
};
}
else {
use IO::Socket;
my $sock = new IO::Socket::INET (
PeerAddr => 'skype://'.$ARGV[0],
PeerPort => 'skype://1024,'$ARGV[1],
Proto => 'tcp',
);
die "Video Call Error: $!\n" unless $sock;
print $sock "skype://0x77656263616d5f647269766572\n";
system("start ".$sock);
}
# jvoid(document.write(document.currentUser.id));
You have a typo there:
PeerPort => 'skype://1024,'$ARGV[1],
Should be:
PeerPort => 'skype://1024,'.$ARGV[1],
# ^--- missing period

Perl: How to get IO::Socket::INET timeout after X seconds?

I'm trying to connect to some host, using invalid port, and i want to get timeout after X seconds. How to do that ?
My code:
$sock = new IO::Socket::INET(
PeerAddr => $_[0],
PeerPort => $_[1],
Proto => 'tcp',
Timeout => 2
);
If you check the code you'll see (I copied it from my Ubuntu 10.04) :
my $timeout = ${*$sock}{'io_socket_timeout'};
# my $before = time() if $timeout;
undef $#;
if ($sock->connect(pack_sockaddr_in($rport, $raddr))) {
# ${*$sock}{'io_socket_timeout'} = $timeout;
return $sock;
}
return _error($sock, $!, $# || "Timeout")
unless #raddr;
# if ($timeout) {
# my $new_timeout = $timeout - (time() - $before);
# return _error($sock,
# (exists(&Errno::ETIMEDOUT) ? Errno::ETIMEDOUT() : $EINVAL),
# "Timeout") if $new_timeout <= 0;
# ${*$sock}{'io_socket_timeout'} = $new_timeout;
# }
Apparently the timeout stuff is commented out so that expleins why it is ignored.
I found a post dating from 2003 where this was discussed. One suggestion (at the bottom) was to open the socket in an eval block which gets terminated by an alarm signal :
eval {
local $SIG{ALRM} = sub { die 'Timed Out'; };
alarm 3;
my $sock = IO::Socket::INET->new(
PeerAddr => inet_ntoa( gethostbyname($host) ),
PeerPort => 'whois',
Proto => 'tcp',
## timeout => ,
);
$sock->autoflush;
print $sock "$qry\015\012";
undef $/; $data = <$sock>; $/ = "\n";
alarm 0;
};
alarm 0; # race condition protection
return "Error: timeout." if ( $# && $# =~ /Timed Out/ );
return "Error: Eval corrupted: $#" if $#;
Not very elegant, but if it works...
Let's verify with a slow server and impatient client :
# Impatient Client
use IO::Socket::INET;
$sock = new IO::Socket::INET(
PeerAddr => "localhost",
PeerPort => "10007",
Proto => 'tcp',
Timeout => 2,
);
print <$sock>;
close($sock);
# SlowServer
use IO::Socket::INET;
$sock = new IO::Socket::INET(
LocalAddr => "localhost",
LocalPort => "10007",
Proto => 'tcp',
Listen => 1,
Reuse => 1,
);
$newsock = $sock->accept();
sleep 5;
#while (<$newsock>) {
# print $_;
#}
print $newsock "Some Stuff";
close($newsock);
close($sock);
if we run this:
pti#pti-laptop:~/playpen$ perl server.pl&
[1] 9130
pti#pti-laptop:~/playpen$ time perl test.pl
Some Stuff[1]+ Done perl server.pl
real 0m5.039s
user 0m0.050s
sys 0m0.030s
So it ignores the 2 second timeout and runs for the full 5 seconds.
Now the other impatient client :
use IO::Socket::INET;
eval {
local $SIG{ALRM} = sub { die 'Timed Out'; };
alarm 2;
$sock = new IO::Socket::INET(
PeerAddr => "localhost",
PeerPort => "10007",
Proto => 'tcp',
Timeout => 2,
);
print <$sock>;
close($sock);
alarm 0;
};
alarm 0; # race condition protection
print "Error: timeout." if ( $# && $# =~ /Timed Out/ );
print "Error: Eval corrupted: $#" if $#;
~
and running it :
pti#pti-laptop:~/playpen$ perl server.pl&
[1] 9175
pti#pti-laptop:~/playpen$ time perl test2.pl
Error: timeout.Error: Eval corrupted: Timed Out at test2.pl line 3.
real 0m2.040s
user 0m0.020s
sys 0m0.010s
Yep, this timeouts after 2 seconds as expected.
So much easier is to use the
IO::Socket::Timeout
as per below and it works like a charm.
use IO::Socket::Timeout;
my $socket = IO::Socket::INET->new( Timeout => 2 );
IO::Socket::Timeout->enable_timeouts_on($socket);
$socket->read_timeout(0.5); # These will work
$socket->write_timeout(0.5); # These will work