0

I'm trying to send an XML request to IP:port, but cURL always times out. However, the endpoint is up and running. Am I specifying the URL wrong? This is what I have:

$ip = '90.179.113.54';
$port = '5500';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://' . $ip . ':' . $port);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 4);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$result = curl_exec($ch);

The $xml variable is just the XML I'm sending, so don't worry about that. The server on this port should return an XML response which I suppose I'm capturing in $result. However, this connection always ends in a timeout - when I enter the IP/port into the browser, it doesn't time out. It returns an XML response which the browser is unable to process.

Telnet response:

telnet 90.179.113.54 5500
Trying 90.179.113.54...
Connected to 54.113.broadband12.iol.cz.
Escape character is '^]'.
telnet 90.179.113.54 5500
Trying 90.179.113.54...
Connected to 54.113.broadband12.iol.cz.
<?xml version="1.0" encoding="Windows-1250" standalone="yes"?>
<RESPONSE TYPE="0" MODUL="" LANG=""><ERROR ERRNUM="0" ERRMESSAGE="0-OK" ATTRIBUT=""/></RESPONSE>
JakeFox
  • 39
  • 1
  • 1
  • 6
  • try have a look here http://stackoverflow.com/questions/18697422/send-xml-data-to-webservice-using-php-curl – Luca Giardina Jan 18 '17 at 11:13
  • @LucaGiardina This code gives me an infinite spinning circle. Just waiting and waiting. I think that's because of the huge timeout value. If there was a lower value, it would time out as well. – JakeFox Jan 18 '17 at 11:19
  • your CURLOPT_POSTFIELDS missed a "arg = ".$xml, maybe it's the problem give it a try.. – Luca Giardina Jan 18 '17 at 11:21
  • @LucaGiardina You mean `curl_setopt($ch, CURLOPT_POSTFIELDS, "xmlRequest=" . $xml);`? That's what I copied from the URL you supplied. Not working. – JakeFox Jan 18 '17 at 11:23
  • *"However, this connection always ends in a timeout - when I enter the IP/port into the browser, it doesn't time out."* -- do you run the PHP code on the same computer as the browser? Different computers may use different routes to reach the remote server. Also, even when they are on the same computer, it's possible that the browser uses a proxy and the PHP code tries to connect directly (these are also different routes). – axiac Jan 18 '17 at 12:15
  • @axiac I run the PHP code on my test environment (localhost). The browser is on the same machine/network. However, I don't know if cURL on localhost takes the public IP address as the browser does, or if it's 127.0.0.1 – JakeFox Jan 18 '17 at 12:23
  • `127.0.0.1` is not involved in any way in this issue. Try to increase the timeout in the PHP code. I ran `time curl http://90.179.113.54:5500 -i` and it reported 12 seconds to get an answer. – axiac Jan 18 '17 at 12:38
  • @axiac Yes, I got 12.467s response time too. Thanks, I'll give it a go. – JakeFox Jan 18 '17 at 12:48
  • guys, it ends with a timeout because curl is waiting for the server to send \r\n\r\n , which in the HTTP protocol separates response header from response body, but that never comes (because this server doesn't speak http). so curl timeouts waiting for the body – hanshenrik Jan 18 '17 at 14:16

2 Answers2

0

This port is not open, try to visit: http://90.179.113.54:5500/

CETb
  • 344
  • 1
  • 3
  • 11
  • I tried it, the browser returns `ERR_INVALID_HTTP_RESPONSE`. That doesn't mean the port is down, right? It just means it returned an XML response, not an HTTP response. – JakeFox Jan 18 '17 at 11:32
  • Possible, port response not in http format. You can test it in another way trough windows cmd: Telnet 90.179.113.54 5500 – CETb Jan 18 '17 at 11:43
  • Yep. You right. The port is for XML communication, i am not sure if you cant trough CURL communicate with the service. Looks like XML Socket Server. See documentation: http://www.php.net/manual/en/sockets.examples.php You have to send request, and immediately receive response. You have some documentation / examples of this service ? – CETb Jan 18 '17 at 13:10
  • I am not going to be able to use sockets on the production server. There already is an implementation in cURL, so it is definitely possible. I just don't have the code at hand, so I cannot use the current stable solution. Thanks for your help though. – JakeFox Jan 18 '17 at 13:23
  • 1
    if there is a curl implementation with this server, it's probably using CURLOPT_PROTOCOLS => CURLPROTO_TELNET , because it definitely isn't HTTP – hanshenrik Jan 18 '17 at 14:47
0

the server does not speak HTTP, and you tell curl that its a http url.

since it's not a HTTP server, do not try to speak HTTP with it. that's what you're doing wrong here (you tell curl that it's a HTTP url, and curl try to speak HTTP with the server).

it appears to just speak TCP/ASCII (or utf-8?) XML, so try that.

$sock=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_connect($sock,'90.179.113.54',5500);
socket_write($sock,$xml);//???
$read_total='';
while(false!==($read_now=socket_read($sock,999,PHP_BINARY_READ))){
    if(strlen($read_now)<1){
        break;//...
    }
    $read_total.=$read_now;
}
socket_close($sock);
var_dump($read_total);

also be wary that there's no guarantee that socket_write actually sends all the data in a single call (and it's almost a guarantee that it won't when the size of the data to send is >= 65535 bytes), so to be safe, you should use some write_all function like

function socket_write_all($sock, string $data) {
    $len=strlen($data);
    while($len>0){
        $written=socket_write($sock,$data);
        if($written===false){
            throw new RuntimeException('socket_write failed. errno: '.socket_last_error($sock).'. error: '.socket_strerror(socket_last_error($sock)));
        }
        $len-=$written;
        $data=substr($data,$written);
    }
    return;//all data written
}

also be wary that, sockets are by default blocking (in linux/windows/mac, anyway), but if you explicitly set the socket to non-blocking mode, the send_all function above would use a lot of cpu (like near 100% of 1 core), and there's ways to mitigate that (select()/poll()), but for the sake of simplicity, i suggest you just go with blocking sockets for now (and start thinking about non-blocking sockets when you have everything working, and start with the optimization stage, if it ever comes to that)

hanshenrik
  • 19,904
  • 4
  • 43
  • 89