Question

I've got a problem with part of a CodeIgniter-based application I'm building.

I have to connect to a remote server and have a reasonably detailed set of instructions from the third-party about how to open a socket, send some XML data and receive a response - in VB script. I've translated this into the PHP code below. At the moment, according to my log, data is being written to the server (the log output is shown below). However the fgets() part of the code just seems to be timing out, with no errors or anything... makes things pretty hard to debug.

From what I've read about fsockopen() and fgets(), the following should work, but obviously it doesn't. The problem is with no error messages etc to go on, I'm at a bit of a loss as to how to debug it.

I would appreciate it if anyone who has a spare minute could cast an eye over it just to see if I've made an obvious mistake (or to confirm that what I'm doing is correct for that matter).

Here's the code (I've had to blank out some of it sorry).

public function makeBooking($orderId) {

    // get entire XML file as a string
    $xmlString = $this->getXmlString();

    // replace non-alphanumeric characters
    $xmlString = $this->replaceChars($xmlString);

    // get length of xml string
    $xmlStrCount = mb_strlen($xmlString) + 7;

    // attempt to open socket
    $fp = fsockopen('xxx.xx.xxx.xx', '81', $errno, $errstr, 10); 

    if (!$fp) {

        // couldn't open socket
        log_message('ERROR', "*** Couldn't open socket: $errno $errstr " . ' | line ' . __LINE__ . ' of ' . __FILE__);

    } else {

        log_message('DEBUG', "*** Socket open, connected to remote server ");

        $lf = chr(13).chr(10);

        // opened socket, prepare output
        $output = '"POST xxxxxxxxxxxx.asp HTTP/1.0"' . $lf;
        $output .= '"Accept: */*"' . $lf;                                            
        $output .= '"User-Agent: xxxxxxxxxxx_socket/1.0";' . $lf;
        $output .= '"Content-type: application/x-www-form-urlencoded";' . $lf;
        $output .= '"Content-length: ' . $xmlStrCount . '";' . $lf;
        $output .= '""' . $lf;
        $output .= '"xml_in='.$xmlString.'"';

        // attempt to write output
        $result = fwrite($fp, $output);
        log_message('DEBUG', "***  Bytes written: $result " . ' | line ' . __LINE__ . ' of ' . __FILE__);
        if($result) {
            log_message('DEBUG', "*** Wrote output:$lf$lf$output$lf");
        } else {
            log_message('ERROR', "*** Failed to write output:$lf$lf$output$lf");
        }


        // read data from server until no more responses are sent            
        // while (!feof($fp)) {
        if(!feof($fp)) {
            log_message('DEBUG',"*** Requesting line 1 from remote server" );
           //$line = fgets($fp);
            $line = fgets($fp);
            if($line) {
                log_message('DEBUG',"*** Retreived line 1: " . print_r($line,TRUE) );
            } else {
                log_message('ERROR',"*** Could not retreive line 1" );
            }
        }
        fclose($fp);
        log_message('DEBUG',"*** Closed connection to remote server" );
    }

}

The log. Obviously a lot of it is how I've interpreted the associated results. I've truncated the URL encoded XML data:

    DEBUG - 2012-09-21 14:50:01 --> *** Socket open, connected to remote server 
DEBUG - 2012-09-21 14:50:01 --> ***  Bytes written: 8801  | line 57
DEBUG - 2012-09-21 14:50:01 --> *** Wrote output:

"POST xxxxxxxxxxxx.asp HTTP/1.0"
"Accept: */*"
"User-Agent: xxxxxxxxxxxxx_socket/1.0";
"Content-type: application/x-www-form-urlencoded";
"Content-length: 8630";
""
"xml_in=%26lt%3B%3Fxml+version%3D%26quot%3B1.0%26quot%3B..."
DEBUG - 2012-09-21 14:50:01 --> *** Requesting line 1 from remote server
ERROR - 2012-09-21 14:51:01 --> *** Could not retreive line 1
DEBUG - 2012-09-21 14:51:01 --> *** Closed connection to remote server

Any ideas of where to look would be much appreciated.

-------------- EDIT --------------

Just incase anyone stumbles across this thread with a similar issue, here's what I did in the end, based on robbie's suggestions:

public function createBooking($orderId) {

    // http://php.net/manual/en/book.curl.php

    // get entire XML file as a string
    $xmlString = $this->getXmlString();

    // replace non-alphanumeric characters - can't use htmlentities or htmlspecialchars
    // because remote server uses different codes
    $xmlString = $this->replaceChars($xmlString);

    // get length of xml string
    $xmlStrCount = mb_strlen($xmlString) + 7;

    // prepare output
    $lf = chr(13).chr(10);
    $output = '"Accept: */*"' . $lf;                                            
    $output .= '"User-Agent: xxxxx_socket/1.0";' . $lf;
    $output .= '"Content-type: application/x-www-form-urlencoded";' . $lf;
    $output .= '"Content-length: ' . $xmlStrCount . '";' . $lf;
    $output .= '""' . $lf;
    $output .= '"xml_in='.$xmlString.'"';

    // set curl options
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,"http://xxxxx:xx/xxxxx.asp");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $output);
    // Request the header information in the response. 
    curl_setopt($ch,CURLOPT_HEADER,true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    // Now execute the query
    $response = curl_exec ($ch);
    if(!$response) {
        log_message('ERROR', "*** Curl error: " . curl_error($ch) . ' | line ' . __LINE__ . ' of ' . __FILE__);
        show_error(DEFAULT_ERR_MSG);
    }
    curl_close ($ch);



    // Response is the data. 
    $aLines = explode("\n", $response);  // Splits the resposne into an array so you can process individual lines.
    // etc

    print_r($aLines);

}
Was it helpful?

Solution

Not sure of the error, but you need while (!$feof($fp)) and not 'if' - the while will loop until you get all the responses. That still doesn't fix your problem, so...

You may find this easier if you implement using curl. Much shorter, neater and easier to debug too. http://php.net/manual/en/book.curl.php

<?php

$ch = curl_init();

// Set the various options. replace the xxxx's 
curl_setopt($ch, CURLOPT_URL,"xxxxxxxxxxxx.asp");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'xml_in=' . $xmlString);
curl_setopt($ch,CURLOPT_USERAGENT,'xxxxxxxxxxx_socket/1.0');

// Request the header information in the response. You're example gets the header, but you may not need it, so change to false if not
curl_setopt($ch,CURLOPT_HEADER,true);

// Now execute the query
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec ($ch);
curl_close ($ch);

// Response is the data. 
$aLines = explode("\n", $response);  // Splits the resposne into an array so you can process individual lines.
// etc

?>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top