Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

IO::Socket problem

Status
Not open for further replies.

ionstorm101

Programmer
Jun 18, 2005
9
IE
Ok, this program im writing is part of a challenge on a site. Basically I have to connect to a page, take the output, parse out a string, append that string to a url and then connect to that url to get the solution. The following is my code

Code:
#!usr/bin/env perl -w

use IO::Socket;


$sock = new IO::Socket::INET(PeerAddr => '[URL unfurl="true"]http://www.bright-shadows.net/challenges/programming/get_started/tryout.php',[/URL]
			     PeerPort => 80,
			     Proto => 'tcp');

die "Error opening socket/connecting: $!" unless $sock;

$buffer = <$sock>;

$buffer =~ /'+(.+)'+/;

$solution = "[URL unfurl="true"]http://www.bright-shadows.net/challenges/programming/get_started/solution.php?solution=";[/URL]
$solution .= $1;

$new_sock = new IO::Socket::INET(PeerAddr => $solution,
				 PeerPort => 80,
				 Proto => 'tcp');

die "Error opening socket/connecting: $!" unless $new_sock;

while($new_sock){
  print "$_";
}


close($sock);
The parsing of the string etc works fine but when i go to run it i get this error
Code:
[nnp@localhost perl]$ perl connect.pl
Error opening socket/connecting: Invalid argument at connect.pl line 10.
For the life of me I cant see whats wrong although im sure its only something basic.

By the way, could someone also tell me what the form of recv() is when you are using IO::Socket. I know the normal recv() when you are just using Socket is recv(Socket_Handle, buffer) but what should i put in for the socket handle here?


Any help is appreciated, thanks,

ionstorm.
 
The main problem is that:
'
is not a valid PeerAddr (i.e. a hostname or ip address), even though it may be a valid URL. There's a difference.

You need to connect to the host first, then request the page you want from the server. Programming at this level (the socket interface level is relatively low level, especially for an established interface such as HTTP), you have to understand the interface protocol you are dealing with. For HTTP you must make a request to the server first, then read the response. Plus, this all happens from the _same_ socket.

Also, $sock should be treated like a FH (or use the class methods). So read <$sock> instead of $sock

for example:
Code:
use IO::Socket;

my $sock = new IO::Socket::INET(
                PeerAddr => '[URL unfurl="true"]www.bright-shadows.net',[/URL]
                PeerPort => 'http(80)',
                Proto => 'tcp');

die "Error opening socket/connecting: $!" unless $sock;

my $document = '/challenges/programming/get_started/tryout.php';
my $request = "GET $document HTTP/1.0\n\n";

print $sock $request;

while ( <$sock> ){
  print $_;
}
Unless you are doing this for educational purposes, there are much better, higher level interface modules to HTTP communication. See, for example, HTTP::Request, LWP::UserAgent, LWP::Simple

jaa
 
In this part

Code:
while (<$sock>){

I will have to take the input and get the part of the text i need pretty quickly (1 second time limit).

When does that stop reading? (does it wait for a \n or how does the server signal its done sending?)

the reason I was using $buffer = <$sock>; is cause i only wanted to read in the first line sent and i dont know how the server signifies its done sending data/

Thanks mate.
 
It doesn't matter whether the request is done being read, if all you need if the first line then your code is fine. Although, the first line of an HTTP response is usually the official response code, something like 'HTTP/1.1 200 OK'. This all assumes you have a proper http server listening on the other end. If the desired line _is_ the first line returned in the response, you can drop (close) the first socket, $sock, when you get the line. But you still need to send the '$solution' request to the server before reading on the second socket, $new_socket.

To strictly answer your question, the <$sock> stops reading when there are no more bytes to read on the socket. The time scale for this is << 'pretty quickly'

jaa

 
Damn, I forgot that the http header would be part of the response. It is a proper fully functional http server im connecting to so i assume it will use standard responses.

In that case its not the first line I want at all, its the first line of the data section.

Would the best way to read in the header and the data to be read in the data one line at a time using while(<$sock>) and concatenate each new line onto the previous lines so the data is just one big string, then use a regex to extract what i want?
 
Ok i decided to use LWP instead but i've ran into trouble with this aswell. Here is my code:

Code:
#!/usr/bin/env perl

use LWP 5.64;


$browser = LWP::UserAgent->new; #Create a UserAgent object

$url = "[URL unfurl="true"]http://www.bright-shadows.net/challenges/programming/get_started/tryout.php";[/URL]

$response = $browser->get($url,
'User-Agent:'=> 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4',
'Accept:'=> 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
'Accept-Language:'=> 'en-us,en;q=0.5',
'Accept-Encoding:'=> 'gzip, deflate',
'Accept-Charset:'=> 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive:'=> '300',
'Referer:'=> '[URL unfurl="true"]http://www.bright-shadows.net/challenges/programming/get_started/tryout.php',[/URL]
'Cookie:' => 'PHPSESSID=49269ae5d14501c60e31392be93d2642',
'Connection:' => 'keep-alive');

print $response->content;

You have to be logged in to get to the URL so I assumed usin g my session cookie would do it. All i get when i print the response though is the html of a page asking me to login. Initially all i was sending was the $url and the Cookie. The reason i have included the referer etc is i thought it might need that. I copied in an exact copy of a http header that my browser uses. Im lost as to why this isnt working?

As a side note, could someone tell me while i always have to prefix my program names with "perl" when i go to run them? I thought using #!/usr/bin/env perl stopped this. e.g to run a script i have to type perl script.pl?

Thanks,
ionstorm
 
I tried using the "cookie jar" method also but to no avail. I create a file called cookies.txt in the same directory as the perl program with the example cookie i posted above in it but when i ran the script i got the following output

Code:
[nnp@main perl]$ perl connectCook.pl
cookies.txt does not seem to contain cookies at /usr/lib/perl5/vendor_perl/5.8.6
/HTTP/Cookies.pm line 426, <FILE> line 1.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>HTTP-Error 404</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" type="text/css" href="/styles.css">
<style type="text/css">
a {text-decoration:underline;color:#D08000;}
a:hover {text-decoration:underline;color:#FFFFFF;}
td.a {padding:0px;color:#FFFFFF;}
td.b {padding-left:2mm;padding-top:0px;padding-bottom:0px;padding-right:0px;}
</style>
</head>
<body class="usual">
<div class="bkgnd_metall" style="padding:1mm;margin:0px;">
  <span class="home_moduletitle">HTTP-Error 404</span>
  <div style="font-family:'Verdana';font-size:9pt;margin:0px;padding:1mm;border-
width:2px;border-style:solid;border-color:#000000 #FFFFFF #FFFFFF #000000;backgr
ound-color:#405070;color:#FFAA00;text-align:left;">
Sorry, but the requested document could not be found:
<p style="background-color:#607090;margin:1mm;padding:1mm;text-align:center;bord
er-style:solid;border-width:1px 0px;border-color:#FFFFFF;color:#FFFFFF;font-fami
ly:'Verdana';font-size:10pt;">[URL unfurl="true"]http://www.bright-shadows.net/challenges/programmi[/URL]
ng/get_started/tryout.ph</p>
If you think this might be an error (broken link or something like that), please
 <a href="/private_messages/send_private_message.php?input_touser=Erik&input_tit
le=Website-problem&input_message=[URL unfurl="true"]www.bright-shadows.net/challenges/programming/get_started/tryout.ph">inform[/URL] a webmaster</a>, so that we can fix the problem.
<table cellspacing="0" style="font-size:8pt;text-align:left;margin-top:1mm;margin-bottom:0px;margin-left:1mm;margin-right:0mm;">
  <tr>
    <td class="a">- History:</td>
    <td class="b"><a href="javascript:history.back()">back</a></td>
  </tr>
  <tr>
    <td class="a">- Referer:</td>
    <td class="b"><a href=""></a></td>
  </tr>
</table>
  </div>
</div>
</body>
</html>
As well as that when i checked the cookie file all that was in it was
#LWP-Cookies-1.0
Im assuming that means perl will create a new cookie file using cookies it recieves but how do i specify ones to use?

(by the way, those arent my actual cookies in case anyone gets any ideas :p)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top