I am running into a silly problem: I need to get a certain number of bytes, then close the connection. I've found I can extract the "Content Length" from the header, and use the length to determine just how many more bytes I should get before severing the connection. However, it appears I have made a mistake. It is only getting 40 bytes, instead of 2428 (as it should). Perhaps I am not using fgets() correctly?
Here is the code:
private static function Send($URL, $Data) {
$server = parse_url($URL, PHP_URL_HOST);
$port = parse_url($URL, PHP_URL_PORT);
// If the parsing the port information fails, we will assume it's on a default port.
// As such, we'll set the port in the switch below.
if($port == null) {
switch(parse_url($URL, PHP_URL_SCHEME)) {
case "HTTP":
$port = 80;
break;
case "HTTPS":
$port = 443;
break;
}
}
// Check if we are using a proxy (debug configuration typically).
if(\HTTP\HTTPRequests::ProxyEnabled) {
$server = \HTTP\HTTPRequests::ProxyServer;
$port = \HTTP\HTTPRequests::ProxyPort;
}
// Open a connection to the server.
$connection = fsockopen($server, $port, $errno, $errstr);
if (!$connection) {
die("OMG Ponies!");
}
echo "===========================================================<BR>";
echo "Connection Open<BR>";
echo "The Time is " . date("H:i:su", time()) . "<BR>";
echo "Sending Request<BR>";
fwrite($connection, $Data);
echo "Request Sent.";
echo "The Time is " . date("H:i:su", time()) . "<BR>";
$responseheader = "";
$responsebody = "";
/*
\HTTP\HTTPRequests::$start = NULL;
\HTTP\HTTPRequests::$timeout = 10;
// #todo: Rewrite this. Should keep checking for '/r/n/r/n', then check for a content length header. If found, keep grabbing bytes, then close. If not, then close immediately.
while(!\HTTP\HTTPRequests::safe_feof($connection, \HTTP\HTTPRequests::$start) && (microtime(true) - \HTTP\HTTPRequests::$start) < \HTTP\HTTPRequests::$timeout)
{
$response .= fgets($connection);
}
*/
echo "Getting Response<BR>";
echo "The Time is " . date("H:i:su", time()) . "<BR>";
while(!feof($connection) && !(strlen(strstr($responseheader,"\r\n\r\n"))>0)) {
$responseheader .= fgets($connection);
}
echo "The Header is fully received at " . date("H:i:su", time()) . "<BR>";
echo "Header (raw):" . "<BR>";
echo "/////////////////////////////////////////////<BR>";
echo $responseheader . "<BR>";
echo "/////////////////////////////////////////////<BR>";
if((strlen(strstr($responseheader,"Content-Length:"))>0)) {
$contentlength = ((int)(\Extract\Extract::GetContentLength($responseheader)));
//for($i = 0; $i < $contentlength; $i++) {
$responsebody .= fgets($connection, $contentlength);
//}
echo "The Body is fully received at " . date("H:i:su", time()) . "<BR>";
echo "Body (raw):" . "<BR>";
echo "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}<BR>";
echo $responsebody . "<BR>";
echo "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}<BR>";
echo "<B>!Content length is " . strlen($responsebody) . ". It should be " . $contentlength . "!</B><BR>";
}
echo "Response Received.<BR>";
echo "The Time is " . date("H:i:su", time()) . "<BR>";
fclose($connection);
echo "Connection Closed.<BR>";
echo "The Time is " . date("H:i:su", time()) . "<BR>";
echo "Exiting Send() method.<BR>";
echo "===========================================================<BR>";
echo "<BR>";
return $responseheader . $responsebody;
}
And here is the output:
===========================================================
Connection Open
The Time is 15:57:29000000
Sending Request
Request Sent.The Time is 15:57:29000000
Getting Response
The Time is 15:57:29000000
The Header is fully received at 15:57:29000000
Header (raw):
/////////////////////////////////////////////
HTTP/1.1 207 Multi-Status Date: Wed, 11 Apr 2012 19:57:18 GMT Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.14 with Suhosin-Patch mod_ssl/2.2.8 OpenSSL/0.9.8g mod_wsgi/2.0 Python/2.5.2 mod_perl/2.0.3 Perl/v5.8.8 X-Powered-By: PHP/5.2.4-2ubuntu5.14 DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule Content-Location: /davical/caldav.php/rwr26/home/ ETag: "8378ead7e628deafd91ec99dc180ad74" X-DAViCal-Version: DAViCal/0.9.9; DB/1.2.9 Content-Length: 2428 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/xml; charset="utf-8"
/////////////////////////////////////////////
The Body is fully received at 15:57:29000000
Body (raw):
{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}
{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}
!Content length is 40. It should be 2428!
Response Received.
The Time is 15:57:29000000
Connection Closed.
The Time is 15:57:29000000
Exiting Send() method.
===========================================================
Why am I doing it this way? Apparently, I was running into some sort of a timeout error, which makes each connection stay open for 30 seconds (yes, 30 whole seconds). So I wrote this code to get the exact number of bytes, then close. Any help is greatly appreciated.
I changed the content line "$responsebody .= fgets($connection, $contentlength);" to "$responsebody .= stream_get_line($connection, $contentlength);". Thing is wicked fast now, and works.
Related
I might be asking the wrong question here, but I cant seem to figure out where this is coming form. I am using both the HTTP Request2 and NET URL2 libraries in order to send some GET request to the Vuforia web services. This all works fine, but everytime I send a request, it also shows said request on screen.
GET d41d8cd98f00b204e9800998ecf8427e Mon, 09 Dec 2019 22:49:52 GMT /summary/ba2246f8cd29466899c69b8d05af09a1
The code that I use to get the above text appear on screen is as follows.
Main code:
<?php if(sizeof($items) > 0){
foreach($items as $item){
echo '<tr>';
echo'<td>'.$item['itemid'].'</td>';
echo'<td>'.$item['name'].'</td>';
echo'<td>'.$item['surname'].'</td>';
echo'<td>'.$item['phone'].'</td>';
$recos = $targetdata = json_decode(CheckVuforiaTarget("ba2246f8cd29466899c69b8d05af09a1"), true);
echo'<td>'.$recos['current_month_recos'].'</td>';
}
} else echo '<tr><td>Geen kandidaten</td></tr>';?>
Script holding the CheckVuforiaTarget function:
function CheckVuforiaTarget($vuforiaid){
$vuforiaTargetTracker = new TargetTracker($vuforiaid);
$response = $vuforiaTargetTracker->TargetTracker();
return ($response);
//print_r($vuforiaResult);
}
TargetTracker class:
<?php
require_once 'HTTP/Request2.php';
require_once 'SignatureBuilder.php';
// See the Vuforia Web Services Developer API Specification - https://developer.vuforia.com/resources/dev-guide/retrieving-target-cloud-database
// The DeleteTarget sample demonstrates how to delete a target from its Cloud Database using the target's target id.
// * note that targets cannot be 'Processing' and must be inactive to be deleted.
class TargetTracker{
//Server Keys
private $access_key = "...";
private $secret_key = "...";
private $url = "https://vws.vuforia.com";
private $requestPath = "/summary/";
private $request;
private $targetId = "";
public function __construct($targetId) {
$this->targetId = $targetId;
}
function TargetTracker(){
$this->requestPath = $this->requestPath . $this->targetId;
return $this->execTargetTracker();
}
public function execTargetTracker(){
$this->request = new HTTP_Request2();
$this->request->setMethod( HTTP_Request2::METHOD_GET );
$this->request->setConfig(array('ssl_verify_peer' => false));
$this->request->setURL( $this->url . $this->requestPath );
$this->setHeaders();
try {
$response = $this->request->send();
if (200 == $response->getStatus()) {
return $response->getBody();
} else {
//echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
// $response->getReasonPhrase(). ' ' . $response->getBody();
return $response->getBody();
}
} catch (HTTP_Request2_Exception $e) {
return $e->getMessage();
}
}
private function setHeaders(){
$sb = new SignatureBuilder();
$date = new DateTime("now", new DateTimeZone("GMT"));
// Define the Date field using the proper GMT format
$this->request->setHeader('Date', $date->format("D, d M Y H:i:s") . " GMT" );
// Generate the Auth field value by concatenating the public server access key w/ the private query signature for this request
$this->request->setHeader("Authorization" , "VWS " . $this->access_key . ":" . $sb->tmsSignature( $this->request , $this->secret_key ));
}
}
?>
Both HTTP/Request2.php(and everything it came with) and SignatureBuilder.php are both default scripts/classes I've downloaded from the internet without altering them.
Now with my basic understanding of PHP, i've tried to find anything related to an echo or whatever command would show this on screen, but I can't seem to find it.
Does someone have some pointers for me, so I can figure out the source?
Thanks in advance!
The code you provided has no echo/print output that would explain the message you see. The echo/print statement must be somewhere else.
My php code have been working fine. And suddenly i got very strange string in response data.
Every response data is like below.where is "87,0" and"3e,0" come from? How can i get rid of them?(They appears before and after every response data.)
HTTP/1.1 200 OK
Date: Fri, 14 Nov 2014 01:57:40 GMT
Server: Apache
X-Powered-By: PHP/5.4.34
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html
87
a:1:{i:0;s:116:"http://www.nytimes.com/2014/09/15/sports/basketball/united-states-wins-fiba-world-cup-title-in-a-rout-of-serbia.html";}
0
HTTP/1.1 200 OK
Date: Fri, 14 Nov 2014 01:57:40 GMT
Server: Apache
X-Powered-By: PHP/5.4.34
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html
3e
a:1:{i:0;s:44:"http://www.bbc.com/news/in-pictures-29204063";}
0
foreach($template_arr as $tkey => $template)
{
$keyword = self::getKeyword($template, $typename);
$keyword = urlencode($typename);//encode because it is going to be send through url
$urlPre = self::getURLPre('news');
$urlrule = self::getURLRule($template); //actually it is used in both siteSearch and urlrule,but urlrule seems unnecessary
$s = stream_socket_client("$sochost:$socportno", $errno, $errstr, $soctimeout, STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT);
if ($s)
{
$sockets[$template] = $s;
$out = "GET /DataAC/Search/Search_Bridge_G.php?keyword=$keyword&resultSize=$resultSize&urlPre=$urlPre&urlrule=$urlrule&template=$template";
$out.= " HTTP/1.1\r\n";
$out.= "Connection: Close\r\n";
$out.= "Host:$sochost\r\n\r\n";
fwrite($s, $out);
}
else
{
echo "$errstr ($errno) ,open sock on search keyword # $keyword on template # $tempalte erro when open search bridge.<br/>\n";
}
}
while (count($sockets))
{
$read = $sockets;
$w = null;
$e = null;
stream_select($read, $w, $e, $soctimeout);
if (count($read))
{
/* stream_select generally shuffles $read, so we need to
compute from which socket(s) we're reading. */
foreach($read as $r)
{
$template = array_search($r, $sockets);
$data = fread($r, $convenient_read_block);
// A socket is readable either because it has
// data to read, OR because it's at EOF.
if (strlen($data) == 0)
{
//echo "Template " . $template . " closes at " . date('h:i:s') . "</br>";
$responseData = $result[$template];
echo "!!!!!!!!!!!!!!!$responseData!!!!!!!!!!!!!!!";
$responseArray=unserialize(substr($responseData,strpos($responseData,"\r\n\r\n")+4)); //get serialize array from respose data and unserialize it ,"+4" means we don't need \r\n\r\n
//var_dump($responseArray);
$urlarr = $responseArray;
// assemble result array start
if (!empty($urlarr))
{
$template_url_arr[$template] = $urlarr[0];
$timenow = date('Y-m-d H:i:s', time());
echo "</br>######### Machine search : keyword:#" . $typename . " target url:" . $urlarr[0] . " timestamp: $timenow" . "#########</br>";
}
else
{
echo "</br> ######### Template url arr empty when query keyword #" . $keyword . " under template #" . $template . " #########</br>";
}
// assemble result array end
fclose($r);
unset($sockets[$template]);
}
else
{
if(!isset($result[$template]))//init the array element or there will be a warning
$result[$template]= "";
$result[$template].= $data;
}
}
}
else
{
/* A time-out means that *all* streams have failed
to receive a response. */
echo "Time-out!\n";
break;
}
}
script:Search_Bridge_G.php
require_once '../../global.php';
//require_once('UTIL/MyFileUtil.php');
//require_once('UTIL/MyDocUtil.php');
require_once 'DataAC/Search/GetGSearchLink.php';
error_reporting(E_ALL);
$keyword=$_GET['keyword'];
$keyword=preg_replace('/\s+/', '%20', trim($keyword)); //replace ' ' with %20
$resultSize=$_GET['resultSize'];
$urlPre=$_GET['urlPre'];
$urlrule=$_GET['urlrule'];
$template=$_GET['template'];
$ant = new \DataGenerator\GetLinkG\GetGSearchLink($keyword,$resultSize, $urlPre,$urlrule);
$urlarr = $ant->getFilteredURL($template);
/*
echo "</br>key:".$keyword."</br>";
echo "</br>rsize:".$resultSize."</br>";
echo "</br>urlpre:".$urlPre."</br>";
echo "</br>urlrule:".$urlrule."</br>";
echo "</br>templa:".$template."</br>";
*/
//var_dump($urlarr);
echo serialize($urlarr);
When an HTTP server cannot determine the Content-Length: in advance, for instance when the output is produced by a dynamic script as opposed to a static file, it will send the output in chunks (as indicated by the Transfer-Encoding: chunked header). Each chunk is prefixed by length expressed in hexadecimal digits. Those are the "strange strings" that you see. The exact details can be found in:
RFC 7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
I'm new to web sockets.. i made my first web socket and i am having problems on running it now!
here is the code of the socket
// set some variables
$host = "127.0.0.1";
$port = 1234;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
if($socket){
echo "socket created .... $socket\n";
}
// bind socket to port
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
if($result){
echo "socket binded ... $result\n";
}
// start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");
if($result){
echo "socket is now listening ... $result";
}
// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
if($spawn){
echo $spawn."\n";
}
// read client input
$input = socket_read($spawn, 1024) or die("Could not read input\n");
if($input){
echo $input."\n";
}
// clean up input string
$input = trim($input);
// reverse client input and send back
$output = strrev($input) . "\n";
socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n");
// close sockets
socket_close($spawn);
socket_close($socket);
now how can i run this code?? i wrote on my xampp shell the following code:
php htdocs/socket/server.php -q
it displays:
socket created....Resource id #4
socket binded... 1
socket is now listening...1 Resource is #5
GET socket/server.php HTTP 1.1
upgrade: WebSocket
connection: Upgrade
Host: http://localhost
sec-WebSocket-key1: 14 53 8501 z4 5R'
sec-WebSocket-key2: S 9\ 2s63, *8460!~MO#
now how can i run it.. how can i send input to it and how can i use it with JavaScript??
i made a JavaScript code but it connect for a second and then disconnect...
here is the javascipt code:
$(document).ready(function() {
if(!("WebSocket" in window)){
$('#chatLog, input, button, #examples').fadeOut("fast");
$('<p>Oh no, you need a browser that supports WebSockets. How about Google Chrome?</p>').appendTo('#container');
}else{
//The user has WebSockets
connect();
function connect(){
var socket;
var host = "ws://localhost:1234/websocket_source_files/myown.php";
try{
var socket = new WebSocket(host);
message('<p class="event">Socket Status: '+socket.readyState);
socket.onopen = function(){
message('<p class="event">Socket Status: '+socket.readyState+' (open)');
}
socket.onmessage = function(msg){
message('<p class="message">Received: '+msg.data);
}
socket.onclose = function(){
message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');
}
} catch(exception){
message('<p>Error'+exception);
}
function send(){
var text = $('#text').val();
if(text==""){
message('<p class="warning">Please enter a message');
return ;
}
try{
socket.send(text);
message('<p class="event">Sent: '+text)
} catch(exception){
message('<p class="warning">');
}
$('#text').val("");
}
function message(msg){
$('#chatLog').append(msg+'</p>');
}//End message()
$('#text').keypress(function(event) {
if (event.keyCode == '13') {
send();
}
});
$('#disconnect').click(function(){
socket.close();
});
}
}//End connect()
});
</script>
<title>WebSockets Client</title>
</head>
<body>
<div id="wrapper">
<div id="container">
<h1>WebSockets Client</h1>
<div id="chatLog">
</div>
<p id="examples">e.g. try 'hi', 'name', 'age', 'today'</p>
<input id="text" type="text" />
<button id="disconnect">Disconnect</button>
</div>
</div>
</body>
</html>
please help me run this code and learn web sockets.. i really need to use them with my school project.
The socket_accept-function will block (wait) until a client connects to it. That's it's standard behavior.
But the functions you execute after you've connected your socket don't block (unless you tell them to). So you'll want to tell your script to wait until it can read from the Socket.
To do so, the socket_set_block-function is used. Also, you might want to check for any possible errors using the socket_last_error-function.
Although, I think Java or C are way bedder suited for using Sockets.
Write another PHP script which would connect to it.
you are not doing the handshake propertly.
from what you posted, you are dealing with the ietf-00 implementation ( https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-00 )
this is old and deprecated, the last one seems to be ietf-10 ( https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-10 ).
a very basic description of the handshake you need can be found here: http://en.wikipedia.org/wiki/WebSockets
(you can find in there the links to the newer and official specifications).
The important part in your case is this:
The Sec-WebSocket-Key1 and Sec-WebSocket-Key2 fields and the 8 bytes
after the fields are random tokens which the server uses to construct
a 16-byte token at the end of its handshake to prove that it has read
the client's handshake.
The handshake is constructed by concatenating the numbers from the
first key, and dividing by the number of spaces. This is then repeated
for the second key. The two resulting numbers are concatenated with
each other, and with the last 8 bytes after the fields.
The final result is an MD5 sum of the concatenated string.[7] The
handshake looks like HTTP but actually isn't. It allows the server to
interpret part of the handshake request as HTTP and then switch to
WebSocket. Once established, WebSocket data frames can be sent back
and forth between the client and the server in full-duplex mode. Text
frames can be sent full-duplex, in either direction at the same time.
The data is minimally framed with just two bytes. Each frame starts
with a 0x00 byte, ends with a 0xFF byte, and contains UTF-8 data in
between. Binary frames are not supported yet in the API. WebSocket
text frames use a terminator, while binary frames use a length prefix.
Now, some code (this will accept one connection, receive a message, and then send a response, just like a very basic and raw example to show how it can be done):
// Just to log to console
function myLog($msg)
{
echo date('m/d/Y H:i:s ', time()) . $msg . "\n";
}
// This will actually read and process the key-1 and key-2 variables, doing the math for them
function getWebSocketKeyHash($key)
{
$digits = '';
$spaces = 0;
// Get digits
preg_match_all('/([0-9])/', $key, $digits);
$digits = implode('', $digits[0]);
// Count spaces
$spaces = preg_match_all("/\\s/ ", $key, $dummySpaces);
$div = (int)$digits / (int)$spaces;
myLog('key |' . $key . '|: ' . $digits . ' / ' . $spaces . ' = ' . $div);
return (int)$div;
}
// This will read one header: value from the request header
function getWebSocketHeader($buffer, &$lines, &$keys)
{
preg_match_all("/([a-zA-Z0-9\\-]*)(\\s)*:(\\s)*(.*)?\r\n/", $buffer, $headers);
$lines = explode("\r\n", $buffer);
$keys = array_combine($headers[1], $headers[4]);
}
// This is where the handshake gets done
function handshake($peer)
{
$buffer = socket_read($peer, 4096, PHP_BINARY_READ);
socket_getpeername($peer, $address, $port);
$peerName = $address . ':' . $port;
myLog('Got from: ' . $peerName . ': ' . $buffer);
getWebSocketHeader($buffer, $lines, $keys);
if (!isset($keys['Sec-WebSocket-Key1']) || !isset($keys['Sec-WebSocket-Key2'])) {
myLog('Invalid websocket handshake for: ' . $peerName);
return;
}
$key1 = getWebSocketKeyHash($keys['Sec-WebSocket-Key1']);
$key2 = getWebSocketKeyHash($keys['Sec-WebSocket-Key2']);
$code = array_pop($lines);
// Process the result from both keys and form the response header
$key = pack('N', $key1) . pack('N', $key2) . $code;
myLog('1:|' . $key1 . '|- 2:|' . $key2 . '|3:|' . $code . '|4: ' . $key);
$response = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n";
$response .= "Upgrade: WebSocket\r\n";
$response .= "Connection: Upgrade\r\n";
$response .= "Sec-WebSocket-Origin: " . trim($keys['Origin']) . "\r\n";
$response .= "Sec-WebSocket-Location: ws://" . trim($keys['Host']) . "/\r\n";
$response .= "\r\n" . md5($key, true); // this is the actual response including the hash of the result of processing both keys
myLog($response);
socket_write($peer, $response);
}
// This is where you can send a frame (delimited by 0x00 and 0xFF)
function send($peer, $message)
{
socket_write($peer, pack('c', (int)0) . utf8_encode($message) . pack('c', (int)255));
}
// This is where you receive a frame (delimited again by 0x00 and 0xFF)
function receive($peer)
{
$buffer = socket_read($peer, 4096, PHP_BINARY_READ);
if (empty($buffer)) {
myLog('Error receiving from peer');
return;
}
return substr($buffer, 1, -1);
}
// Now create a socket
$socket = socket_create_listen(1026);
$peer = socket_accept($socket);
// Do the handshake and wait for an incoming message from the client
handshake($peer);
myLog('Got ' . receive($peer));
// Respond!
send($peer, 'hi there');
socket_close($peer);
socket_close($socket);
EDIT:
this is a very basic html that works in chrome (mine at least):
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window)
{
// Let us open a web socket
var ws = new WebSocket("ws://host:1026");
ws.onopen = function()
{
// Web Socket is connected, send data using send()
ws.send("Message to send");
console.log('send');
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
console.log(received_msg);
var txt = document.createTextNode(received_msg);
document.getElementById('messages').appendChild(txt);
};
ws.onclose = function()
{
// websocket is closed.
console.log('close');
};
}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
}
</script>
</head>
<body>
<div id="sse">
Run WebSocket
</div>
<div id="messages">
</div>
</body>
</html>
Im using this code here: http://www.digiways.com/articles/php/httpredirects/
public function ReadHttpFile($strUrl, $iHttpRedirectMaxRecursiveCalls = 5)
{
// parsing the url getting web server name/IP, path and port.
$url = parse_url($strUrl);
// setting path to '/' if not present in $strUrl
if (isset($url['path']) === false)
$url['path'] = '/';
// setting port to default HTTP server port 80
if (isset($url['port']) === false)
$url['port'] = 80;
// connecting to the server]
// reseting class data
$this->success = false;
unset($this->strFile);
unset($this->aHeaderLines);
$this->strLocation = $strUrl;
$fp = fsockopen ($url['host'], $url['port'], $errno, $errstr, 30);
// Return if the socket was not open $this->success is set to false.
if (!$fp)
return;
$header = 'GET / HTTP/1.1\r\n';
$header .= 'Host: '.$url['host'].$url['path'];
if (isset($url['query']))
$header .= '?'.$url['query'];
$header .= '\r\n';
$header .= 'Connection: Close\r\n\r\n';
// sending the request to the server
echo "Header is: <br />".str_replace('\n', '\n<br />', $header)."<br />";
$length = strlen($header);
if($length != fwrite($fp, $header, $length))
{
echo 'error writing to header, exiting<br />';
return;
}
// $bHeader is set to true while we receive the HTTP header
// and after the empty line (end of HTTP header) it's set to false.
$bHeader = true;
// continuing untill there's no more text to read from the socket
while (!feof($fp))
{
echo "in loop";
// reading a line of text from the socket
// not more than 8192 symbols.
$good = $strLine = fgets($fp, 128);
if(!$good)
{
echo 'bad';
return;
}
// removing trailing \n and \r characters.
$strLine = ereg_replace('[\r\n]', '', $strLine);
if ($bHeader == false)
$this->strFile .= $strLine.'\n';
else
$this->aHeaderLines[] = trim($strLine);
if (strlen($strLine) == 0)
$bHeader = false;
echo "read: $strLine<br />";
return;
}
echo "<br />after loop<br />";
fclose ($fp);
}
This is all I get:
Header is:
GET / HTTP/1.1\r\n
Host: www.google.com/\r\n
Connection: Close\r\n\r\n
in loopbad
So it fails the fgets($fp, 128);
Is there a reason you aren't using PHP's built-in, enabled-by-default ability to fetch remote files using fopen?
$remote_page = file_get_contents('http://www.google.com/'); // <- Works!
There are also plenty of high-quality third-party libraries, if you need to do something like fetch headers without thinking too hard. Try Zend_Http_Client on for size.
The flaw is here:
$good = $strLine = fgets($fp, 128);
if(!$good)
{
echo 'bad';
return;
}
fgets() returns either a string on success, or FALSE on failure. However, if there was no more data to be returned, fgets() will return the empty string (''). So, both $good and $strLine are set to the empty string, which PHP will happily cast to FALSE in the if() test. You should rewrite as follows:
$strLine = fgets($fp, 128);
if ($strLine === FALSE) { // strict comparison - types and values must match
echo 'bad';
return;
}
There's no need for the double assignment, as you can test $strLine directly.
I'm writing an MSN client in PHP. This is my code for so far:
$socket = fsockopen("messenger.hotmail.com", 1863);
echo '<b>Connected to 1st server.</b><br />';
//Send MSNP version
fputs($socket, "VER 0 MSNP10 CVR0\r\n");
echo fread($socket, 5000) . '<br />';
//Send user-agent
fputs($socket, "CVR 1 0x0409 php ".phpversion()." i386 MSNMSGR 7.0.0000 MSMSGS ".$_POST["username"]."\r\n");
echo fread($socket, 5000) . '<br />';
//Send username
fputs($socket, "USR 2 TWN I ".$_POST["username"]."\r\n");
//Read XFR
$xfr = fread($socket, 5000);
echo $xfr . '<br />';
$xfr = explode(" ", $xfr);
//Connect to second server
$server2 = explode(":", $xfr[3]);
$socket = fsockopen($server2[0], (int)$server2[1]);
echo '<b>Connected to 2nd server.</b><br />';
//Send MSNP version
fputs($socket, "VER 0 MSNP10 CVR0\r\n");
echo fread($socket, 5000) . '<br />';
//Send user-agent
fputs($socket, "CVR 1 0x0409 php ".phpversion()." i386 MSNMSGR 7.0.0000 MSMSGS ".$_POST["username"]."\r\n");
echo fread($socket, 5000) . '<br />';
//Send username
fputs($socket, "USR 2 TWN I ".$_POST["username"]."\r\n");
//Read USR
$usr = fread($socket, 5000);
echo $usr . '<br />';
$usr = explode(" ", $usr);
//Connect to Nexus
$nexus = fsockopen("nexus.passport.com", 443);
$request_nexus = "GET /rdr/pprdr.asp HTTP/1.1\r\n";
$request_nexus .= "Host:nexus.passport.com\r\n";
$request_nexus .= "User-Agent:MSNphp/1.0 (PHP; U; PHP 5; en-US)\r\n";
$request_nexus .= "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
$request_nexus .= "Accept-Language:en-us,en;q=0.5\r\n";
$request_nexus .= "Keep-Alive:300\r\n";
$request_nexus .= "Connection:keep-alive\r\n";
$request_nexus .= "Cache-Control:max-age=0\r\n\r\n";
fputs($nexus, $request_nexus);
echo fread($nexus, 5000);//This is line 54, which causes the error
My result is this:
Connected to 1st server.
VER 0 MSNP10
CVR 1 1.0.0000 1.0.0000 1.0.0000 http://msgr.dlservice.microsoft.com http://download.live.com/?sku=messenger
XFR 2 NS 207.46.124.241:1863 0 65.54.239.21:1863
Connected to 2nd server.
VER 0 MSNP10
CVR 1 1.0.0000 1.0.0000 1.0.0000 http://msgr.dlservice.microsoft.com http://download.live.com/?sku=messenger
USR 2 TWN S ct=1249043921,rver=5.5.4177.0,wp=FS_40SEC_0_COMPACT,lc=1033,id=507,ru=http:%2F%2Fmessenger.msn.com,tw=0,kpp=1,kv=4,ver=2.1.6000.1,rn=1lgjBfIL,tpf=b0735e3a873dfb5e75054465196398e0
Fatal error: Maximum execution time of 30 seconds exceeded in C:\wamp\apps\msnphp\chat.php on line 54
I get a timeout error when I connect to Nexus. But when I make a request to https://nexus.passport.com/rdr/pprdr.asp in Firefox, I get the result I want (checked with HttpFox). Why does Nexus take so much to to respond to my script? In Firefox it takes 2 seconds.
Does anyone know what I am doing wrong?
Whilst you are connecting to the SSL port (443) on nexus.passport.com , you aren't actually sending the information encrypted: therefore Nexus is just waiting for the encrypted data to arrive and eventually timing out (your PHP script is timing out before hand).
You'll probably be best using Curl to send the information to nexus as it's able to handle the SSL connection for you (why reinvent the wheel?).
Your script is running to long. PHP has a mechanism where it kills a script if it runs longer then specified in settings. You can change this value (it's called max_execution_time) in your php.ini or you can use set_time_limit() function to alter it in your script.