Sockets

Started by benthehutt, February 16, 2006, 10:22:02 AM

Previous topic - Next topic
I've got a humdinger of a question about Perl.  I've been using Perl for a few weeks now, and I just started into sockets and all the fun stuff that comes with that.  So here's the problem.  I have a script running on a system on the network that creates a socket on some random port like this:

Code  perl Select
#!/usr/bin/perl -w

#For myComputer

use IO::Socket;
my $localhost = 'myComputer';
my $localport = 6703;
my $protocol = 'tcp';

my $socket = new IO::Socket::INET(LocalHost=>$localhost,
                           LocalPort=>$localport,
                           Proto=>$protocol,
                           Listen=>1,
                           Reuse=>1
                           );
&Failed unless $socket;

my $new_sock = $socket->accept();
while(defined(<$new_sock>)) {
   print $_;
}
close($socket);


close($socket);

sub Failed{
   print "\nSocket connection failed--could not create:\n";
   print "$protocol port on $localhost at $localport\n\n";
}


So when I start up this script it does its business then waits for something to connect to it so it can accept the connection and print whatever input it gives the script.

So then I wrote another script to connect to it locally or remotely and give it something to print out:

Code  perl Select
#!/usr/bin/perl -w

use IO::Socket;

my $host = 'myComputer';
my $port = 6703;
my $protocol = 'tcp';

my $socket = new IO::Socket::INET   (
                           PeerAddr=>$host,
                           PeerPort=>$port,
                           Proto=>$protocol
                           );
&Failed unless $socket;

print $socket "Hellooo!\n";
close($socket);


sub Failed{
   print "\nSocket connection failed--could not create:\n";
   print "$protocol port on $host at $port\n\n";
}


Then the script just prints and closes the socket.  But whenever I run them together, starting the first one first, then the second, it says:

"Use of uninitialized value in print at sockets.pl line 20, <GEN1> line 1."

and quits.  So how do I manipulate input into the socket and why is this screwing up?  The second script executes fine--I think...

Anyway, any help would be appreciated on the subject.
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.

Never did like perl... powerful language though.

Anyway, a bit of research and experimenting solved it:

Try changing the problematic part (line 20) to something like:

my $new_sock = $socket->accept();
while(defined($line = <$new_sock>)) {
   print $line;
}


Should then work ... or it did on my tests anyway. But don't sak me details cause I know crap all about perl ...


"My Terminal is my Soul"

You don't like Perl?  Aw, too bad--it's powerful stuff, though, I suppose you know C.  Anyway, that's a good idea, I'll try it this afternoon when I'm back in the office.  I suppose it was stupid of me to try and print a string when it wasn't defined.

Also, do you have any idea why you put <>'s around input in Perl?  I've heard C is similar--though I don't actually know C.

By the way, where did you do your "research?" I could swear I looked everywhere for a stupid answer.
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.

February 17, 2006, 01:28:35 PM #3 Last Edit: February 17, 2006, 01:29:29 PM by Metgod
Well, I don't like perl in that it's a messy language (looks) IMO. Same with Java btw. I like readability and other things similar to that more than efficiency (usually anyway -- there are some times I feel different though). I know others agree there, but yes it is powerful and quite useful none the less.

Of course, yes, C is too (especially for system programming). As is Python (which I don't know but tempted to). I'm actually (gasp) tempted to learn C++. I really should learn sed (other than the -i option) and awk too. Anyway...

No idea about the < and >. Could probably find out by doing a bit of googling though. And I can't honestly think of anything similar in C (mostly because I don't know what the idea is in perl) and maybe the fact I am a bit off lately.

I have another friend that does perl, and he once suggested 'perldoc'. Check 'man perldoc' for more info. One example is 'perldoc -f <function_name>'. You can also use, e.g., 'perldoc IO::Socket'.

Quite useful information.

Where I did my research....

I went to perl.com, and they have a section on IPC (which is interprocess communication and sockets are an example). Then saw the specific idea on that page:

http://search.cpan.org/dist/perl/pod/perlipc.pod

And then I tested and it worked.

Hope that helps...
"My Terminal is my Soul"

I agree with you on the whole ugly thing.  If you like pretty, why don't you learn C++, it's real perdy!  Well, I like it at least.  Though I'm really only comparing it to Perl and ADA and a handful of other butt-ugly languages (save Q-Basic).
As far as the <> question, it really doesn't matter--I just don't understand it.  Take the following code for example:

#!/usr/bin/perl -w

open(INFILE, "fileName.txt");
my @data = <INFILE>;


Whereas, if you assign a variable a value in any other way, there's no <>'s.  I was just wondering if you knew persay, but it doesn't really matter.  I'll be back with more questions later...right now I'm trying to learn how to reverse engineer web-APIs...
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.

Woo-hoo!  I finally got to test out that socket thing--and it totally worked.  Thanks Metty.  Now to do something useful with it... ;D
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.

So this is my idea:  chatroom.  I mean, not for actual application--just to figure out new things to do with Perl and sockets.  My idea is to have a script that creates a new socket.  Then a generic script that connects to that socket from wherever the heck you want to be.  Then as many scripts can run from wherever--since the one script will be written generally...it's an idea anyway.  I'll write a "prototype" first...
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.

Attempt 1:  One-Way Communication

My first attempt is first of all a failure, but still very enlightening. First, I took the dual script approach where one script fools with creating and binding the socket, and the second one connects and talks to it.  Here's the script that creates the socket, you also specify the host and port:

Code  perl Select
#!/usr/bin/perl -w

use IO::Socket::INET;

#Sees if you entered the correct command line arguments
unless (scalar(@ARGV) == 2){print "\nUsage:  perl $0 [host] [port]\n";exit;}
my ($host, $port) = @ARGV;

#Creates a new socket and calls failed() if it couldn't make one
my $socket = new IO::Socket::INET(   Proto=>'tcp',
                           LocalHost=>$host,
                           LocalPort=>$port,
                           Listen=>1,
                           Reuse=>1) || &Failed;

print "\nListening on $host:$port for users...\n";

#Accept incoming connections
my $listen = $socket->accept();

#Call recursive subprogram--this is kinda dirty, but it's only a "first draft"
&hear;

sub hear{
#Here's the part with the problem.  This command will block everything
#else until it gets something, then it prints
   while(defined ($line = <$listen>)) {
      print $line;
#If you type in "q" the script exits
      if ($line=~/\bq\b/){close($socket);exit;}
   }
#Recursive call
   &hear;
}

sub Failed{
   print "\nSocket connection failed--could not create:\n";
   print "TCP port at $host:$port\n\n";
   exit;
}


Now then, the problem with this, as labeled in my comments, is that the script blocks everything until it gets input, then it prints.  But I'll come back to this later.  The script that connects to this socket follows:



Code  perl Select
#!/usr/bin/perl -w

use IO::Socket;

unless (scalar(@ARGV) == 2){print "\nUsage:  perl $0 [host] [port]\n";exit;}
my ($host, $port) = @ARGV;

my $socket = new IO::Socket::INET   (
                           PeerAddr=>$host,
                           PeerPort=>$port,
                           Proto=>'tcp'
                           );

&Failed unless $socket;

#Another dirty recurive subprogram
&print;

sub print{
#Get some input...
   $line = <STDIN>;
#Print it to the socket
   print $socket $line;
#Quit if you type "q"
   if($line=~/\bq\b/){
      $socket->autoflush(1);
      close($socket);
      exit;
   }
#Recursive call
   &print;
}

sub Failed{
   print "\nSocket connection failed--could not connect to:\n";
   print "Could not connect to $host:$port\n";
   exit;
}


Here again the program blocks until something is typed in...But it works nicely if you want to creep someone out "Matrix-style" with words being typed on their screen--but not much for anything else.

So I'm currently researching a few alternatives.  The first is to use Perl's select() command to tell me what's waiting and then execute code based on that.  The second option is to use fork or some other means to manipulate two distinct threads at once.  Then one could be watching things coming in from the socket, the other could be watching things coming in from the keyboard.

So concludes my failed attempt number 1.  I'll be back with results--hopefully...

And if anyone has any suggestions, please speak up!  I've never done any socket programming so I know I'm doing this a stupid way.  But then again--that's how you learn. ;D
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.

Various techniques, yeah.

Select is a nice way.... I'd actually recommend you to check out these two documents for a nice overview. It's for C but the idea is the same I'd think.

http://beej.us/guide/bgnet/

http://beej.us/guide/ipc/

There is also a BSD socket guide out there. The above ones I think are HP-UX (been a while since I last checked it).

It's a damn shame but I actually started a decent guide on raw sockets but never got to finishing it and it's since lost (much like all my other would be documents). Anyway... if this doesn't help let me know and I'll try to be of more help.

But back to my slumber of sorts for now ...

"My Terminal is my Soul"

btw, might want to check these too:

http://www.erlenstar.demon.co.uk/unix/faq_toc.html

http://www.linuxprofilm.com/articles/linux-daemon-howto.html

The latter is probably more useful for you... since it's relavent to your problem. I know there is another set of documents.. trying to remember where.. will post back if I can find it.

I kind of miss this stuff.. might have to get back in to it soon. I wonder if I'll make it a year though (or even a month, haha)
"My Terminal is my Soul"

February 23, 2006, 11:03:09 PM #10 Last Edit: February 23, 2006, 11:04:15 PM by Metgod
Ah, yes... ibm.com is _loaded_ with programming information.

http://www-128.ibm.com/developerworks/linux/library/l-sprace.html?ca=dgr-lnxw06RACE
http://www-128.ibm.com/developerworks/linux/library/l-recurs.html
http://www-128.ibm.com/developerworks/linux/library/l-reent.html
http://www-128.ibm.com/developerworks/linux/library/l-shlibs.html

and much much more! The only problem is something I think zerored has as his sig... (that or godaigo.. sorry, can't really remember) so much to learn, so little time... Words of the wise for sure.

Edit:

bloody bbs... killing the link. Anyway, just check that site out and the directory .. since it has lots of info.


"My Terminal is my Soul"

Oh and one more thing that might be of use ...

Large programs are a great way to learn how to code! Some might scoff and say you have to know a language to actually gain a lot and do well on modifying big programs, but that's complete and utter nonsense....

Learning by example is very productive ... and if you have the motivation (and enjoy whatever it may be [for me it's muds]), you'll find you learn a lot (mostly since it's easier to work on something you enjoy). Could be through the original coder's mistakes/bugs, or even non-bugs. Also goofing around with it and changing things to your liking. Even fixing your own mistakes is useful. Can get ideas from it and then write test programs (and check it out with debuggers) and so on.

CVS (or any revision control system) is quite useful as well (since you can keep a whole record of your own stupidity [which happens to me a lot, haha] and also brilliance... and then you can simply revert back to a working copy if you screw up too badly). Over time it'll be worth it ...


Ok.. enough rambling from me. Hope this of use to someone :)

"My Terminal is my Soul"

Wow, this outta keep me busy *forever*.  Thanks for the help metty, I probably won't be able to work on this stuff until at least Monday, but thanks nonetheless. ;D
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.

Glad to be of help. I once upon a time refused to register at ibm (it's free but I hate registering), but the other day I did and it was well worth it.

And by the by I found this:

man 2 select_tut

which should work on any linux box. For C again but it'll give you a nice overview.
"My Terminal is my Soul"

SMF spam blocked by CleanTalk