I am using stream_socket_client() on my development server (linux box, PHP 5.2) to pull data asynchronously and it works flawlessly. I pull the same code down to my local windows laptop, running a local WAMP (PHP 5.4) stack and my code out errors out saying the connection is closed when I try to fwrite() the header to the connection. Removing the STREAM_CLIENT_ASYNC_CONNECT parameter from the stream_socket_client line allows the header to be sent. My question is whether anyone knows if there is a problem with stream_socket_client() either with Windows or with PHP version 5.4?

This has me really scratching my head.

Sample Code:

function get_api_data($url, $format = "json", $debug = 0) {
  // Explode out the parameters.
  $url_array = explode("/", $url);
  // Is it http or https?
  $method = strtolower(array_shift($url_array));
  // Pop off an array blank.
  array_shift($url_array);
  // Get the host.
  $host = array_shift($url_array);
  // Get the rest of the url.
  $get_params = "/" . implode("/", $url_array);
  // Additional parameters.
  $addr = gethostbyname($host);
  $timeout = 60;

  // Set up socket connection parameters.
  switch ($method) {
    case "http:":
      $socket_type = "tcp://";
      $port = ":80";
      break;

case "https:":
  $socket_type = "ssl://";
  $port = ":443";
  break;

default:
  echo "Only HTTP and HTTPS protocols currently supported";
  break;

  }// End switch($method);

  // Make an asynchronous data connection.
  $fp = stream_socket_client($socket_type . $addr . $port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT );
  if ($debug == 1 && $fp) {
    echo "<br />Connection to " . $socket_type . $addr . $port . " Achieved<br />";
  }
  if ($debug == 1 && !$fp) {
    echo "<br />Connection to " . $socket_type . $addr . $port . " Not Achieved<br />";
  }

  // If the connection is made, send the request in the header:
  if ($fp !== false) {
    $headers = "GET $get_params HTTP/1.0\r\n";
    $headers .= "Host: $host\r\n";
    $headers .= "Accept: */*\r\n";
    $headers .= "Content-type: application/$format; charset=utf8\r\n";
    $headers .= "Connection: close\r\n\r\n";
    if ($debug == 1) {
      echo "<br />Headers to be sent are:<br ><pre>$headers</pre><br />";
    }

/* lines below were added as an attempt to fix the issue.  It didn't, so taking them out for now. */
//if(stream_set_blocking($fp, 0) === false) echo "<br />Cannot set Stream Blocking Mode<br />";
//else echo "<br />Stream Blocking Mode is set<br />";

if($fp !== false)$fwrite=fwrite($fp, $headers);
if($fwrite === false) echo "<br />Cannot write header<br />";
else echo "<br />Header written $fwrite bytes<br />";

// This line keeps the system from locking up...
stream_set_timeout($fp, 1);
// Now, retrieve the data.
$data = stream_get_contents($fp,-1);

// Close the connection.
fclose($fp);
  } // End if($fp).

  // If the format is json, the delimiter is "{", if xml, the delimiter is "<".
  if ($format == "json") {
    $delimiter = "{";
  }
  if ($format == "xml") {
    $delimiter = "<";
  }

  // Strip out header information, leaving only the data.
  $data_arr = explode($delimiter, $data);
  $data_header = array_shift($data_arr);
  $data = implode($delimiter, $data_arr);
  if ($data != "") {
    $data = $delimiter . $data;
  }

  $pubs_arr = array();
  // Convert the xml format to an array.
  if ($format == "xml") {
    $pubs_arr = json_decode(json_encode((array) simplexml_load_string($data)), 1);
  }
  // Convert the JSON format to an array.
  if ($format == "json") {
    $pubs_arr = json_decode($data, TRUE);
  }
  // Append the data header into the array, for testing.
  $pubs_arr['dataHeader'] = $data_header;

  return ($pubs_arr);
}// End function get_api_data($url,$format="json",$debug=0).

Sample execution of the function:

$myDataArr = get_api_data("http://store.samhsa.gov/api/r/xml/websitelist?terms=Recovery","xml",1);

echo "<br /><pre>" . print_r($myDataArr) . "</pre><br />";

Error message I get is "Notice: fwrite(): send of 155 bytes failed with errno=10057 A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied", with a line reference that goes to line 60, where I write the headers, which is:

if($fp !== false)$fwrite=fwrite($fp, $headers);

Any ideas or thoughts would be very welcome...

    Makes no difference if the firewalls are up or down. That was my first thought as well. Unfortunately, it doesn't seem to help.

      Probably over my head then ... permissions?

        Don't know. Found and installed a PHP version 5.3 package for my Uniserver web server. I switched the PHP version to 5.3, and I'm still seeing the issue. My dev server is using PHP version 5.2, due to Drupal 7's reliance on pass-by-reference, but Uniserver currently only backdates to version 5.3. I'll check with the developers and see if there is a way I can package my own PHP version 5.2 to switch to. If I can do that, I can prove or eliminate my version speculation...

          1. Does this really make sense?
            STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT
            I would suspect that either one will be used. Which one would probably depend on which bit is checked first.

          2. Does gethostbyname provide the same address on the failing system?

          3. Why are you not checking $errno and $errstr values?

            According to every code example I've seen that shows stream_connect_client() being run asynchronously, both parameters are being used, with a pipe symbol between them. It doesn't seem to work otherwise, in my testing.

            The same IP address is returned by both systems.

            The error occurs on the fwrite(), not on stream_client_connect(). Stream_connect_client()'s $errno comes back as zero (0) and $errstr comes back empty.

            I know that stream_connect_client() functionality has differed between different PHP subversions, so I'm trying to get my local system backdated to version 5.2, in order to test version compatibility. If this is the case, I'll have to file a bug report or something...

              Write a Reply...