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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reuse socket connection multiple times

Status
Not open for further replies.

jamesp0tter

Programmer
Feb 20, 2003
119
PT
Hello all !

I'm developing a personal side project, and basically I need to get various bits of a remote file. I use the "Range" field in the HTTP request to accomplish this, and it's all working perfectly.

But, as I need various bits, initiating a connection, sending headers, getting response, and closing connection, just to repeat the process the next time seems a bit excessive and unnecessary.

So, basically, I was thinking opening the connection first, then use a function to get all the bits I need (separately, not every response in one result), and finally close it.

Problem is, I cannot figure out the correct headers to send !

Basically:
Code:
$fp = fsockopen($url['host'], 80, $errno, $errstr, 30);
if (!$fp)
	die("Error: $errstr ($errno)");

function get_range($start,$len) {

	global $fp,$url;
	
	$start = intval($start);
	$end = $start+intval($len)-1;

	$resp = '';

    	$out = "GET {$url['path']}{$url['query']} HTTP/1.1\r\n";
    	$out .= "Range: bytes={$start}-{$end}\r\n";
    	$out .= "Host: {$url['host']}\r\n";
    	$out .= "Connection: Keep-Alive\r\n\r\n";

    	fwrite($fp, $out);
    	while (!feof($fp)) {
        	$resp .= fgets($fp, 128);
    	}

	return substr($resp,strpos($resp,"\r\n\r\n")+4);
}

for ($i=0;$i<100;$i++)
	// get_range(x,y) and do what i need with that specific response
	
fclose($fp);
I need this to work, and don't go into an infinite loop like it's doing now.

Maybe a problem with the header "Connection" Maybe I need something to tell the socket it's being reused ?

Thanks in advance!

jamesp0tter

p.s.: sorry for my (sometimes) bad english :p
 
my gut-feel is that this won't work. even with the keep-alive.

but as a last gasp you might try emulating a browser by spawning a forked process for each segment request. or increase the timeout setting on the server.

or, probably easiest, change your script to use cURL

remember also that you must use http 1.1 (i note that your headers already specify this).

lastly, you might, instead, look at changing the server side to present an easy web-service API for you to interact with
 
Thanks for the reply jpadie. The purpose of this project is to connect to any server on the internet (server-side access and API isn't an option), and cURL doesn't really prove necessary in this case.

I got it to work :)

Problem was feof() only returns true when we tell the server to close the connection after sending us the data ("Connection: Close" does this). As we don't want the connection dropped, we need a) "Connection: Keep-Alive" and b) other method to keep reading the contents of the stream until no bytes are left.

Here's my solution (bold are the key changes):

Code:
$fp = fsockopen($url['host'], 80, $errno, $errstr, 30);
if (!$fp)
	die("Error: $errstr ($errno)");

function get_range($url,$start,$len) {

	global $fp,$url;

	$start = intval($start);
	$end = $start+intval($len)-1;
	
    $out = "GET {$url['path']}{$url['query']} HTTP/1.1\r\n";
    $out .= "Range: bytes={$start}-{$end}\r\n";
    $out .= "Host: {$url['host']}\r\n";
[b]    $out .= "Connection: Keep-Alive\r\n\r\n";[/b]

    fwrite($fp, $out);
    
[b]	$resp = fread($fp,1);
	while (bl($fp) != 0)
		$resp .= fread($fp,1);[/b]

	return substr($resp,strpos($resp,"\r\n\r\n")+4);
}

( ... etc code ... )

fclose($fp);

[b]function bl ($s) {	// bytes left
	$b = stream_get_meta_data($s);	
	return $b['unread_bytes'];
}[/b]

Hope this helps anyone with the same problem in the future ;)

jamesp0tter

p.s.: sorry for my (sometimes) bad english :p
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top