Can't create socket using IO::Socket - perl

when I run the following code, the execution is just hanging there, No response at all.
does any of you can tell me what's wrong with the sample code?
use strict;
use warnings;
use IO::Select;
use IO::Socket;
my $s = new IO::Socket (
LocalPort => 8889,
Proto => 'tcp',
Listen => 16,
Reuse => 1
);
die "could not create socket $!\n" unless $s;

If you provide arguments to the IO::Socket constructor it demands a Domain argument. Check out the full source here, specifically the configure subroutine which gets called from the constructor if you've provided arguments.
sub new {
...
return scalar(%arg) ? $sock->configure(\%arg)
: $sock;
}
sub configure {
my($sock,$arg) = #_;
my $domain = delete $arg->{Domain};
croak 'IO::Socket: Cannot configure a generic socket' unless defined $domain;
....
}
Perhaps you're thinking of IO::Socket::INET?

what's wrong with the sample code?
IO::Socket is a generic super class for Perl sockets.
You need to replace the IO::Socket with IO::Socket::INET.

Related

Thrift::TException=HASH(0x25d18e0) error

I am trying to connect to Hive via Perl module Thrift::API::HiveClient and below is the code to connect to Hadoop hive and retrieve the data
#!/usr/bin/perl
use DBI;
use DBI::DBD;
use Data::Dumper;
use List::MoreUtils qw(uniq);
use DateTime;
#use warnings 'all';
use POSIX qw(strftime);
use LWP::Simple;
use Thrift;
use Thrift::API::HiveClient;
use Data::Dumper;
my $latest_return;
# Database connection
my $client = Thrift::API::HiveClient->new(
host => 'localhost',
port => '10000',
);
$client->connect or die "Could not connect";
my $rh = $client->execute('select * from devtest.users');
my $return = [];
while ($latest_return = $client->fetch($rh)) { # will die with an error if it fails
print $latest_return;
}
When I execute the above script it throws below message
Thrift::TException=HASH(0x25d18e0)
I also tried Dumper to print the result nothing got printed.
any help is much appreciated.
OK, so the problem here is - you're doing something that's failing.
The module you import - Thrift::API::Hiveclient warns:
THIS CODE IS ALPHA-QUALITY, EXPERIMENTAL, AND LIKELY FLAMMABLE
Having said that - what is happening here, is for some the action is failing, and it's dieing with an error object.
That error object has status code and message with it. (I don't think this is idomatic perl though, it's more like Java :)).
So in the connect there's an error, that's not being handled properly so your code is dying.
A Thrift::TException is a fairly simple sort of object:
package Thrift::TException;
sub new {
my $classname = shift;
my $self = {message => shift, code => shift || 0};
return bless($self,$classname);
}
1;
Literally just a message and a code.
To get at that message, you'll need to dereference your object, and that's what doesn't seem to be happening.
My best guess is the _open method in Thrift::Socket is returning an error, and the HiveClient isn't actually trapping/handling it.
It should be doing an eval and trapping the error, and then unpacking the TException.
Somewhere here:
sub connect {
my ($self) = #_;
$self->_transport->open;
}
Maybe. I'm not 100% sure, because Moo might do something cute with die, but I can't find or see where that is.
So short answer - you're probably failing to connect, to be sure you'd need to grab that error message - to do that you'll need to hack the Hiveclient to eval the operation. This is what you signed up for by using a module that's "Alpha quality".

How do I get requestId of FCGI process in Perl using Net::FastCGI?

I have an application that calls FCGI responder to process some tasks and I need to find whether the FCGI responder receives and returns same reqeust IDs.
The FCGI responder is written in Perl and uses FCGI module.
According to FastCGI specification, I can find the information by looking up FastCGI records.
I found Net::FastCGI library may be suitable for solving this issue, but I'm not sure how to utilize the library.
If my fcgi script looks like below, how can I use Net::FastCGI to dump contents of FastCGI record?
use FCGI;
my $count = 0;
my $request = FCGI::Request();
while($request->Accept() >= 0) {
print("Content-type: text/html\r\n\r\n", ++$count);
}
You can use Net::FastCGI if you want to dump FastCGI records. Net::FastCGI is very low level and requires understanding of the FastCGI protocol.
Following code shows a simple client that connects to a FastCGI application given as the first argument and outputs string representations of records sent by the application.
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket qw[];
use Net::FastCGI::Constant qw[:type :role];
use Net::FastCGI::IO qw[read_record write_record write_stream];
use Net::FastCGI::Protocol qw[build_params dump_record build_begin_request_body];
use warnings FATAL => 'Net::FastCGI::IO';
use constant TRUE => !!1;
my $command = shift #ARGV;
my $socket = IO::Socket::INET->new(Proto => 'tcp', Listen => 5)
or die qq/Could not create a listener socket: '$!'/;
my $host = $socket->sockhost;
my $port = $socket->sockport;
defined(my $pid = fork())
or die qq/Could not fork(): '$!'/;
if (!$pid) {
close STDIN;
open(STDIN, '+>&', $socket)
or die qq/Could not dup socket to STDIN: '$!'/;
exec { $command } $command
or die qq/Could not exec '$command': '$!'/;
}
close $socket;
$socket = IO::Socket::INET->new(Proto => 'tcp', PeerHost => $host, PeerPort => $port)
or die qq/Could not connect to '$host:$port': '$#'/;
write_record($socket, FCGI_BEGIN_REQUEST, 1, build_begin_request_body(FCGI_RESPONDER, 0));
write_stream($socket, FCGI_PARAMS, 1, build_params({}), TRUE);
write_stream($socket, FCGI_STDIN, 1, '', TRUE);
while () {
my ($type, $request_id, $content) = read_record($socket)
or exit;
warn dump_record($type, $request_id, $content), "\n";
last if $type == FCGI_END_REQUEST;
}
Example output:
fcgi-echo.pl is the example app you gave in your question and fcgi-dump.pl is the above code.
$ perl fcgi-dump.pl ./fcgi-echo.pl
{FCGI_STDOUT, 1, "Content-type: text/html\r\n\r\n1"}
{FCGI_STDOUT, 1, ""}
{FCGI_END_REQUEST, 1, {0, FCGI_REQUEST_COMPLETE}}
You wouldn't. There's no sense in using Net::FastCGI when you're already using FCGI. The request ID, if you need it, is available in $request->{id} after calling $request->Accept. It's not clear what you mean by "receives and returns same request IDs" though.

Cannot use subroutine name in socket created by Perl RPC::Serialized::Server::NetServer::Single

I want to use Perl module and wrap it into a standalone socket which would publish the subroutines from the module to other programmes. However, I probably cannot overcome namespace issues, since in the client script, I am still getting an error message:
RPC::Serialized::X::Application\',\'MESSAGE\' => \'No handler for 'predejPOS' .
My server script:
use RPC::Serialized::Server::NetServer::Single;
use RPC::Serialized::Handler::HashTree;
my $s = RPC::Serialized::Server::NetServer::Single->new({
net_server => {log_file => '', port => 20203 },
rpc_serialized => {handler_namespaces => ''},
});
$s->run;
My client script:
use RPC::Serialized::Client::INET;
my $client = RPC::Serialized::Client::INET->new({
io_socket_inet => {PeerAddr => '127.0.0.1', PeerPort => 20203,}
});
my $result = $client->predejPOS('flu-like');
My module (HastTree.pm):
package RPC::Serialized::Handler::HashTree;
require Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(predejPOS);
use base 'RPC::Serialized::Handler';
our $VERSION = '0.01';
sub predejPOS {
my %POS;
$POS{'flu-like'}='<JJ>';
return $POS{$_[0]};
};
1;
I am using Windows 7, Strawberry Perl 5.12.3, and the module sits on the correct address
(C:\PROGS\Strawberry\perl\site\lib\RPC\Serialized\Handler). The function predejPOS is recognised inside the server script (ie. I can print its result from it), but I cannot access it through the client-server communication. I assume that it has something to do with the subtle difference between calling the function and calling the method. I am afraid that it is probably something simple, but even after a substantial effort and googling I was not able to make it work.
Thanks in advance!
Well I eventually solved it by myself:
First, I got completely wrong the concept of calling functions - over the network you can only call so called RPC Handlers. Moreover for each handler there must be a module in RPC::Serialized::Handler directory with the same name and a specific structure with only one subroutine inside called invoke(). Thus I changed my module (named now 'PredejPOS.pm') to:
package RPC::Serialized::Handler::PredejPOS;
{
$RPC::Serialized::Handler::PredejPOS::VERSION = '0.01';
}
use strict;
use warnings FATAL => 'all';
use base 'RPC::Serialized::Handler';
sub invoke {
my $self = shift;
my $key = shift;
my %POS;
$POS{'flu-like'}='<JJ>';
return scalar $POS{$key};
}
1;
But it was still not working.
Finally secondly I found that under Windows environment, the Perl Data::Serialize module does not work properly.
In the package Serialized.pm, subroutine recv (row 115), the chomp does not remove the damned Windows line ending '\cM'. When I corrected it, it started working as envisaged. Actually there is a lenghty discussion of this behaviour here ( http://www.perlmonks.org/?node_id=549385 )
Thanks for the suggestions.
For object method the first argument is always the current object instance itself. Sorry, if I am not clear enough, try to figure out the difference from this example:
Try this:
sub predejPOS {
my $self = shift;
my $key = shift;
my %POS;
$POS{'flu-like'}='<JJ>';
return $POS{$key};
};

Can't use an undefined value as a symbol reference

I'm trying to use an API for a Palo Alto Networks software. The code is supposed to submit username and ipaddress of user network logins to a web interface.
When I try using PANs' API with their sample code for a windows machine the following exception is thrown:
Can't use an undefined value as a symbol reference at
C:/Perl/lib/PAN/API.pm line 179 (#1)
PAN::API::UID::login('PAN::API::UID=HASH(0x7fd113828598)', 'SCU-DSM22/pmmertens', 172.16.6.117) called at API_events.pl line 12
This is the code-example that comes with the API documentation:
#!/usr/bin/perl -w
use strict;
use PAN::API;
my $useridagent = '10.0.0.99'; #I changed this to our PAN server address
my $useridapi = PAN::API::UID->new($useridagent);
my $user = $ENV{USERDOMAIN}.'/'.$ENV{USERNAME};
my $ipaddress = unpack('W4',gethostbyname($ENV{COMPUTERNAME}));
$useridapi->login($user,$ipaddress);
I've ensure that all variables are retrieved correctly. Substituting literal values did not help either. Googling this error turned up references about hard and soft references but I don't see any infractions of these rules in the code below.
This is the codeblock from PAN/Api.pm. Line 179 is where the print starts.
sub submit () {
my $self = shift;
use IO::Socket::INET;
use IO::Socket::SSL;
my $socket = IO::Socket::INET->new(PeerAddr => $self->{server},
PeerPort => $self->{port},
Proto => 'tcp');
my $socketssl = IO::Socket::SSL->start_SSL( $socket,
SSL_version =>'TLSv1');
print $socketssl $self->xml;
$socketssl->close;
$socketssl->stop_SSL;
}
Both the IO::Socket::INET and IO::Socket::SSL lines should have error checking. Something like:
my $socket = IO::Socket::INET->new(....)
or die "Failed to create socket: $!"
And:
my $socketssl = IO::Socket::SSL->start_SSL(...)
or die "Failed to start SSL: ".IO::Socket::SSL::errstr();
Although instead of die I might go with Carp::confess.

Perl socket connection

Is it possible to create a socket connection to an open port on an end device.
If the connection drops print something?
I have seen a few examples but they require a server type script and a client, just looking for a client.
Thanks
Perl has sockets built right into it. You just need to load the standard Socket.pm module to get the constants you need.
The perlipc manpage tells you all about this. There are many higher-level modules that get at this more easily than the builtins, however. Some are even standard.
Here’s a CLI example:
% perl -MIO::Socket::INET -E '$him = new IO::Socket::INET "localhost:daytime" // die; print while <$him>'
Tue Jun 28 08:17:13 2011
Consider using the module IO::Socket::INET, http://www.thegeekstuff.com/2010/07/perl-tcp-udp-socket-programming/
A variation of this might fit your need:
use strict;
use warnings;
use constant
{ SOCKET_ERROR_MESSAGE => 'Some socket error message right here!'
, YOU_WANT_TO => 1
};
use IO::Select;
use IO::Socket::INET;
#ARGV = qw<server.domain.tld 8080> unless #ARGV;
sub handle_server_message {
...
}
my $sel
= IO::Select->new(
IO::Socket::INET->new(
PeerAddr => shift
, PeerPort => shift
));
# block until the server sends something that can be read.
while ( my ( $sock ) = $sel->can_read ) {
# you could just do this with $sock->eof...
if ( $sock->error and $sock->eof ) {
die MY_ERROR_MESSAGE if YOU_WANT_TO;
print MY_ERROR_MESSAGE;
}
else {
handle_server_message( $sock );
}
}