Notice using "tcp" insted of "http"
<?
fsockopen("tcp://example.net",80 , $errno, $errstr, 30);
?>
fsockopen
(PHP 4, PHP 5)
fsockopen — Abrir una conexión de sockets de dominio de Internet o Unix
Descripción
Inicia una conexión a través de sockets con el recurso especificado por nombre_host .
PHP soporta el uso de destinos en los dominios de Internet y Unix, tal y como se describe en Lista de Transportes de Sockets Soportados. Una lista de transportes soportados puede recuperarse usando stream_get_transports().
El socket será abierto por omisión en modo de bloqueo. Es posible cambiar a modo de no-bloqueo usando stream_set_blocking().
Lista de parámetros
- nombre_host
-
Si ha compilado el soporte para OpenSSL, usted puede usar un prefijo sobre el nombre_host , ya sea 'ssl://' o 'tls://' para usar una conexión de cliente SSL o TLS sobre TCP/IP para conectarse con el host remoto.
- puerto
-
El número de puerto.
- errno
-
Si se provee, conserva el número de error de nivel de sistema que haya ocurrido en la llamada de sistema connect().
Si el valor devuelto en errno es 0 y la función devolvió FALSE, es un indicio de que el error ocurrió antes de la llamada a connect(). Lo más probable es que esto se deba a un problema con la inicialización del socket.
- errstr
-
El mensaje de error como una cadena.
- tiempo_espera
-
El tiempo de espera de la conexión, en segundos.
Note: Si necesita establecer un tiempo de espera para la lectura/escritura de datos a través del socket, use stream_set_timeout(), dado que el parámetro tiempo_espera de fsockopen() sólo se aplica cuando se conecta con el socket.
Valores retornados
fsockopen() devuelve un apuntador de archivo el cual puede ser usado junto con otras funciones de archivos (como fgets(), fgetss(), fwrite(), fclose(), y feof()). Si la llamada falla, devolverá FALSE.
Registro de cambios
| Versión | Descripción |
|---|---|
| 4.3.0 | Se agregó el soporte para el parámetro tiempo_espera en win32. |
| 4.3.0 | Se agregó el soporte para SSL y TLS sobre TCP/IP. |
| 4.0.0 | Se agregó el soporte UDP. |
| 3.0.9 | Se agregó el parámetro tiempo_espera . |
Ejemplos
Example #1 Ejemplo de fsockopen()
<?php
$da = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$da) {
echo "$errstr ($errno)<br />\n";
} else {
$salida = "GET / HTTP/1.1\r\n";
$salida .= "Host: www.example.com\r\n";
$salida .= "Connection: Close\r\n\r\n";
fwrite($da, $salida);
while (!feof($da)) {
echo fgets($da, 128);
}
fclose($da);
}
?>
Example #2 Uso de conexión UDP
El ejemplo a continuación presenta la forma de recuperar la fecha y hora desde el servicio UDP "daytime" (puerto 13) en su propia máquina.
<?php
$da = fsockopen("udp://127.0.0.1", 13, $errno, $errstr);
if (!$da) {
echo "ERROR: $errno - $errstr<br />\n";
} else {
fwrite($da, "\n");
echo fread($da, 26);
fclose($da);
}
?>
Notes
Note: Dependiendo del entorno, el dominio Unix o el tiempo de espera de conexión opcional pueden no estar disponibles.
En ocasiones, los sockets UDP parecerán haber sido abiertos sin errores, incluso si el host remoto no puede ser contactado. El error sólo se percibirá cuando lea o escriba datos hacia/desde el socket. La razón es que UDP es un protocolo "sin conexión", lo que quiere decir que el sistema operativo no intenta establecer un enlace con el socket hasta que necesite realmente enviar o recibir datos.
Note: Cuando se especifique una dirección numérica IPv6 (p.ej. fe80::1) se debe incluir la IP entre corchetes. Por ejemplo tcp://[fe80::1]:80.
fsockopen
09-Sep-2008 10:28
06-Sep-2008 11:00
My $0.02 on handling chunked transfer encoded output... Has rudimentary error handling.
<?php
//
// Example usage...
//
$server = '127.0.0.1';
$port = '80';
$uri = '/cgi-bin/random-cgi';
$content = 'Your post content...';
$post_results = httpPost($server,$port,$uri,$content);
if (!is_string($post_results)) {
die('uh oh, something went wrong');
} else {
die('Here are your results: ' . $post_results);
}
//
// Post provided content to an http server and optionally
// convert chunk encoded results. Returns false on errors,
// result of post on success. This example only handles http,
// not https.
//
function httpPost($ip=null,$port=80,$uri=null,$content=null) {
if (empty($ip)) { return false; }
if (!is_numeric($port)) { return false; }
if (empty($uri)) { return false; }
if (empty($content)) { return false; }
// generate headers in array.
$t = array();
$t[] = 'POST ' . $uri . ' HTTP/1.1';
$t[] = 'Content-Type: text/html';
$t[] = 'Host: ' . $ip . ':' . $port;
$t[] = 'Content-Length: ' . strlen($content);
$t[] = 'Connection: close';
$t = implode("\r\n",$t) . "\r\n\r\n" . $content;
//
// Open socket, provide error report vars and timeout of 10
// seconds.
//
$fp = @fsockopen($ip,$port,$errno,$errstr,10);
// If we don't have a stream resource, abort.
if (!(get_resource_type($fp) == 'stream')) { return false; }
//
// Send headers and content.
//
if (!fwrite($fp,$t)) {
fclose($fp);
return false;
}
//
// Read all of response into $rsp and close the socket.
//
$rsp = '';
while(!feof($fp)) { $rsp .= fgets($fp,8192); }
fclose($fp);
//
// Call parseHttpResponse() to return the results.
//
return parseHttpResponse($rsp);
}
//
// Accepts provided http content, checks for a valid http response,
// unchunks if needed, returns http content without headers on
// success, false on any errors.
//
function parseHttpResponse($content=null) {
if (empty($content)) { return false; }
// split into array, headers and content.
$hunks = explode("\r\n\r\n",trim($content));
if (!is_array($hunks) or count($hunks) < 2) {
return false;
}
$header = $hunks[count($hunks) - 2];
$body = $hunks[count($hunks) - 1];
$headers = explode("\n",$header);
unset($hunks);
unset($header);
if (!verifyHttpResponse($headers)) { return false; }
if (in_array('Transfer-Coding: chunked',$headers)) {
return trim(unchunkHttpResponse($body));
} else {
return trim($body);
}
}
//
// Validate http responses by checking header. Expects array of
// headers as argument. Returns boolean.
//
function validateHttpResponse($headers=null) {
if (!is_array($headers) or count($headers) < 1) { return false; }
switch(trim(strtolower($headers[0]))) {
case 'http/1.0 100 ok':
case 'http/1.0 200 ok':
case 'http/1.1 100 ok':
case 'http/1.1 200 ok':
return true;
break;
}
return false;
}
//
// Unchunk http content. Returns unchunked content on success,
// false on any errors... Borrows from code posted above by
// jbr at ya-right dot com.
//
function unchunkHttpResponse($str=null) {
if (!is_string($str) or strlen($str) < 1) { return false; }
$eol = "\r\n";
$add = strlen($eol);
$tmp = $str;
$str = '';
do {
$tmp = ltrim($tmp);
$pos = strpos($tmp, $eol);
if ($pos === false) { return false; }
$len = hexdec(substr($tmp,0,$pos));
if (!is_numeric($len) or $len < 0) { return false; }
$str .= substr($tmp, ($pos + $add), $len);
$tmp = substr($tmp, ($len + $pos + $add));
$check = trim($tmp);
} while(!empty($check));
unset($tmp);
return $str;
}
?>
18-Aug-2008 05:34
Sending multiple files with form(modification of sir_reality2001 at yahoo dot com's and Duukkis's scripts):
<?php
$boundary = "AaB03x";
$boundary2 = "BbC04y";
// Build the header
$header = "POST remoteurl HTTP/1.0\r\n";
$header .= "Host: remotehost\r\n";
$header .= "Content-Type: multipart/form-data; boundary=$boundary\r\n";
// attach post vars
foreach($_POST AS $index => $value){
$data .="--$boundary\r\n";
$data .= "Content-Disposition: form-data; name=\"".$index."\"\r\n";
$data .= "\r\n".$value."\r\n";
$data .="--$boundary\r\n";
}
// and attach the file
for ($i=0; $i<count($_FILES['userfile']['name']);$i++)
{
$data .= "--$boundary\r\n";
if ($_FILES['userfile']['name'][$i] != '')
{
$content_file = join("", file($_FILES['userfile']['tmp_name'][$i]));
$data.="Content-Disposition: file; name=\"userfile[$i]\"; filename=\"".$_FILES['userfile']['name'][$i]."\"\r\n";
$data .= "Content-Type: ".$_FILES['userfile']['type'][$i]."\r\n\r\n";
$data .= "".$content_file."\r\n";
$data .="--$boundary\r\n";
}
}
$data .="--$boundary--\r\n";
$header .= "Content-length: " . strlen($data) . "\r\n\r\n";
$fp = fsockopen($remote_server, 80);
?>
21-Jul-2008 07:32
When you try to POST/GET requests via HTTPS over SSL/TLS you should notice this:
<?php
// preconditions
$port = 80 | 443
$host = "www.example.com";
$method = "POST" | "GET";
$contenttype = "text/html" | "text/plain" | "text/xml" | ...;
$data = "<something>";
// script
if($port == 443)
$sslhost = "ssl://".$host;
else
$sslhost = $host;
$fp = fsockopen($sslhost, $port);
fputs($fp, "$method $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
fputs($fp, "Content-type: $contenttype\r\n");
fputs($fp, "Content-length: ".strlen($data)."\r\n");
fputs($fp, "Connection: close\r\n");
fputs($fp, "\r\n");
?>
The server usually does not understand the HTTP-header "Host: XXX" if you provide it with the trailing "ssl://" used by fsockopen(); If you do it anyway you probably get a HTTP 400 back as response. :-)
08-Mar-2008 09:15
An edit to my below function for extra headers support and a bit of debugging
( array("key" => "value") type)
<?php
if(!function_exists("download")){
function download($uri, $port = 80, $extra_headers = NULL){
if(!function_exists("stripos")){
function stripos($str, $needle, $offset=0){
return strpos(strtolower($str),strtolower($needle),$offset);
}/* endfunction stripos */
}/* endfunction exists stripos*/
if(!is_int($port))$port = 80;
if(!is_array($extra_headers))$extra_headers = array();
$uri = strtr( strval($uri), array("http://" => "", "https://" => "ssl://", "ssl://" => "ssl://", "\\" => "/", "//" => "/") );
if( ( $protocol = stripos($uri, "://") ) !== FALSE ){
if( ( $domain_pos = stripos($uri, "/", ($protocol + 3)) ) !== FALSE ){
$domain = substr($uri, 0, $domain_pos);
$file = substr($uri, $domain_pos);
}
else{
$domain = $uri;
$file = "/";
}
}
else{
if( ( $domain_pos = stripos($uri, "/") ) !== FALSE ){
$domain = substr($uri, 0, $domain_pos);
$file = substr($uri, $domain_pos);
}
else{
$domain = $uri;
$file = "/";
}
}
$fp = fsockopen($domain, $port, $errno, $errstr, 30);
if(!$fp){
return FALSE;
}
else{
$out = "GET " . $file . " HTTP/1.1\r\n";
$out .= "Host: " . $domain . "\r\n";
foreach( $extra_headers as $nm => $vl ){
$out .= strtr( strval($nm), array( "\r" => "", "\n" => "", ": " => "", ":" => "") ) . ": " . strtr( strval($vl), array( "\r" => "", "\n" => "", ": " => "", ":" => "") ) . "\r\n";
}
$out .= "Connection: Close\r\n\r\n";
$response = "";
fwrite($fp, $out);
while (!feof($fp)) {
$response .= fgets($fp, 128);
}
fclose($fp);
global $http_response_header;
$http_response_header = array();
if( stripos($response, "\r\n\r\n") !== FALSE ){
$hc = explode("\r\n\r\n", $response);
$headers = explode("\r\n", $hc[0]);
if(!is_array($headers))$headers = array();
foreach($headers as $key => $header){
$a = "";
$b = "";
if( stripos($header, ":") !== FALSE ){
list($a, $b) = explode(":", $header);
$http_response_header[trim($a)] = trim($b);
}
}
return end($hc);
}
else if( stripos($response, "\r\n") !== FALSE ){
$headers = explode("\r\n", $response);
if(!is_array($headers))$headers = array();
foreach($headers as $key => $header){
if( $key < ( count($headers) - 1 ) ){
$a = "";
$b = "";
if( stripos($header, ":") !== FALSE ){
list($a, $b) = explode(":", $header);
$http_response_header[trim($a)] = trim($b);
}
}
}
return end($headers);
}
else{
return $response;
}
}
}/*endfunction download*/
}/*endif no function download*/
?>
27-Dec-2007 11:12
<?php
// Check for new version
$current_version = explode('.', '1.0.00');
$minor_revision = (int) $current_version[2];
$errno = 0;
$errstr = $version_info = '';
if ($fsock = fsockopen("www.exanmple.eu", 80, $errno, $errstr, 30))
{
@fputs($fsock, "GET /ver.txt HTTP/1.1\r\n");
@fputs($fsock, "HOST: www.example.eu\r\n");
@fputs($fsock, "Connection: close\r\n\r\n");
$get_info = false;
while (!@feof($fsock))
{
if ($get_info)
{
$version_info .= @fread($fsock, 1024);
}
else
{
if (@fgets($fsock, 1024) == "\r\n")
{
$get_info = true;
}
}
}
@fclose($fsock);
$version_info = explode("\n", $version_info);
$latest_head_revision = (int) $version_info[0];
$latest_minor_revision = (int) $version_info[2];
$latest_version = (int) $version_info[0] . '.' . (int) $version_info[1] . '.' . (int) $version_info[2];
if ($latest_head_revision == 2 && $minor_revision == $latest_minor_revision)
{
$version_info = '<p style="color:green">OK</p>';
}
else
{
$version_info = '<p style="color:red">neaktualne';
$version_info .= '<br />'Latest_version_info' . $latest_version) . ' ' . sprintf(Current_version_info'. '1.0.00') . '</p>';
}
}
else
{
if ($errstr)
{
$version_info = '<p style="color:red">' . sprintf(Connect_socket_error) . '</p>';
}
else
{
$version_info = '<p>'Socket_functions_disabled'</p>';
}
}
$version_info .= '<p>'Mailing_list_subscribe_reminder'</p>';
echo $version_info;
?>
05-Dec-2007 04:59
Make a ping test with PHP
The problem with fsockopen is you have to known the destination port.
A real ping function could be :
<?php
function php_ping($url) {
$addr=parse_url($url);
$host=$addr['host'];
exec("ping -c 1 -w 1 $host", $list);
if (strpos($list[4],"1 received")>0) {
return true ;
}
return false;
}
?>
But if your router refuse the ping ... the result will be always false > you may test both (fsockopen and ping)
13-Nov-2007 07:13
After several days of trying to get telnet going from php 5.2, i've come up with http://www.dali.net.nz/Telnet.class.php.txt
based on the one found at http://cvs.adfinis.ch/cvs.php/phpStreamcast/telnet.class.php
example usage:
<?php
$telnet = new Telnet('telnethost.example.com');
$telnet->login('username', 'password');
echo $telnet->exec('ifconfig') . "\n";
echo $telnet->exec('ls -lh') . "\n";
$telnet->disconnect();
?>
04-Sep-2007 08:34
I don't know why it's not mentioned here (or am I missing something), but the DEFAULT stream timeout is set according to default_socket_timeout in your php.ini file. Took forever for me to dig that up....
23-Jul-2007 11:32
I was having trouble doing an https in fopen and with fsockopen where the address had ssl://. I was getting error code 114 in the log. After much research i found that there was some ssl conflict trouble with MySQL 5.0.20-5.0.33. It had some functions that were interfering with openssl that showed up in the php install.
http://bugs.mysql.com/bug.php?id=21930
http://bugs.mysql.com/bug.php?id=19289
17-Jul-2007 06:37
I ran into a problem where I needed to make an fsockopen() style connection from one specific ip address on a server with multiple ip aliases. Unfortunately fsockopen() does not allow the specification of a source address making it unsuitable. I could not find any other solutions elsewhere so here is mine for those with php 5.1.0 or greater.
<?php
// connect to the internet using the '192.168.0.100' IP
$opts = array('socket' => array('bindto' => '192.168.0.100:0'));
$context = stream_context_create($opts);
$fp = stream_socket_client("tcp://www.example.com:80", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
?>
Now $fp can be used like a resource handle returned by a vanilla fsockopen() call!
03-Jul-2007 08:58
easy get UIDL.
A code is better than the feof.
<?php
$fp = fsockopen($host, 110, $errno, $errstr, 5);
if ($fp > 0) {
fread($fp,1024);
fputs($fp, "USER $user\r\n");
fread($fp,1024);
fputs($fp, "PASS $pass\r\n");
fread($fp,1024);
fputs($fp, "UIDL\r\n");
fgets($fp,1024);
do {
$line = rtrim(fgets($fp, 1024));
if ($line == '.') break;
list(, $UIDL) = split(' ', $line, 2);
echo $UIDL;
} while ($line != '.');
fputs($fp, "QUIT\r\n");
}
fclose($fp);
?>
26-May-2007 09:29
To check if a Url is Online (with http and https)
Using @fgets to hide Warning when using SSL
(Bug: "Warning: function.fgets SSL: fatal protocol error", http://bugs.php.net/bug.php?id=23220)
<?php
function isOnline($url) {
if (!$url_info = parse_url($url)) {
return false;
}
switch ($url_info['scheme']) {
case 'https':
$scheme = 'ssl://';
$port = 443;
break;
case 'http':
default:
$scheme = '';
$port = 80;
}
$data = "";
$fid = @fsockopen($scheme . $url_info['host'], $port, $errno, $errstr, 30);
if ($fid) {
fputs($fid, 'HEAD ' . (isset($url_info['path'])? $url_info['path']: '/') . (isset($url_info['query'])? '?' . $url_info['query']: '') . " HTTP/1.0\r\n" .
"Connection: close\r\n" .
'Host: ' . $url_info['host'] . "\r\n\r\n");
while (!feof($fid)) {
$data .= @fgets($fid, 128);
}
fclose($fid);
return !empty($data);
} else {
return false;
}
}
?>
HTTP/1.1 requires that all clients support chunked transfer encoding. If you don't want to implement that and just want something simple, make HTTP/1.0 requests instead:
<?php
...
fputs("GET $path HTTP/1.0\r\n");
fputs("Host: $host\r\n");
...etc..
?>
01-Mar-2007 10:17
[EDIT by danbrown AT php DOT net: This note contains a big-fixed version of the user function decode_body(). Fix by (martjean77 at hot dot sapm dot mail dot com) [sic].]
Handling chunked data needs careful handling, because the data can also be compressed inside the chunked data, and chunked data can have many parts, so you need to watch for that. Here a simple example that uses one function decode_header(); to build the header into a key => value array, so it makes it easy to test for the content and transfer types inside the decode_body(); function!
<?php
function decode_header ( $str )
{
$part = preg_split ( "/\r?\n/", $str, -1, PREG_SPLIT_NO_EMPTY );
$out = array ();
for ( $h = 0; $h < sizeof ( $part ); $h++ )
{
if ( $h != 0 )
{
$pos = strpos ( $part[$h], ':' );
$k = strtolower ( str_replace ( ' ', '', substr ( $part[$h], 0, $pos ) ) );
$v = trim ( substr ( $part[$h], ( $pos + 1 ) ) );
}
else
{
$k = 'status';
$v = explode ( ' ', $part[$h] );
$v = $v[1];
}
if ( $k == 'set-cookie' )
{
$out['cookies'][] = $v;
}
else if ( $k == 'content-type' )
{
if ( ( $cs = strpos ( $v, ';' ) ) !== false )
{
$out[$k] = substr ( $v, 0, $cs );
}
else
{
$out[$k] = $v;
}
}
else
{
$out[$k] = $v;
}
}
return $out;
}
function decode_body ( $info, $str, $eol = "\r\n" )
{
$tmp = $str;
$add = strlen ( $eol );
$str = '';
if ( isset ( $info['transfer-encoding'] ) && $info['transfer-encoding'] == 'chunked' )
{
do
{
$tmp = ltrim ( $tmp );
$pos = strpos ( $tmp, $eol );
$len = hexdec ( substr ( $tmp, 0, $pos ) );
if ( isset ( $info['content-encoding'] ) )
{
$str .= gzinflate ( substr ( $tmp, ( $pos + $add + 10 ), $len ) );
}
else
{
$str .= substr ( $tmp, ( $pos + $add ), $len );
}
$tmp = substr ( $tmp, ( $len + $pos + $add ) );
$check = trim ( $tmp );
}
while ( ! empty ( $check ) );
}
else if ( isset ( $info['content-encoding'] ) )
{
$str = gzinflate ( substr ( $tmp, 10 ) );
}
else {
$str = $tmp;
}
return $str;
}
if ( ( $io = fsockopen( "www.yahoo.com", 80, $errno, $errstr, 5 ) ) !== false )
{
$send = "GET / HTTP/1.1\r\n";
$send .= "Host: www.yahoo.com\r\n";
$send .= "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021204\r\n";
$send .= "Referer: http://www.yahoo.com/\r\n";
$send .= "Accept: text/xml,application/xml,application/xhtml+xml,";
$send .= "text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,";
$send .= "image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1\r\n";
$send .= "Accept-Language: en-us, en;q=0.50\r\n";
$send .= "Accept-Encoding: gzip, deflate, compress;q=0.9\r\n";
$send .= "Connection: Close\r\n\r\n";
fputs ( $io, $send );
$send = '';
do
{
$send .= fgets ( $io, 4096 );
} while ( strpos ( $send, "\r\n\r\n" ) === false );
$info = decode_header ( $send );
$send = '';
while ( ! feof ( $io ) )
{
$send .= fread ( $io, 8192 );
}
fclose ( $io );
$send = decode_body ( $info, $send );
echo '<h3>Header Array</h3>';
echo '<pre>';
print_r ( $info );
echo '</pre>';
echo '<h3>Document Body</h3>';
echo $send;
}
?>
29-Jan-2007 09:52
This script checks specific ports so you need to have the correct port open on the server for this to work.
E.g if i have a windows domain controller and it is servering LDAP then the following would be used to check it is online:
<?php
chkServer("MyDC", "389");
?>
for a webserver:
<?php
chkServer("MyWebSvr", "80");
?>
etc etc
--------------------------------------------------------
<?php
// check if a server is up by connecting to a port
function chkServer($host, $port)
{
$hostip = @gethostbyname($host); // resloves IP from Hostname returns hostname on failure
if ($hostip == $host) // if the IP is not resloved
{
echo "Server is down or does not exist";
}
else
{
if (!$x = @fsockopen($hostip, $port, $errno, $errstr, 5)) // attempt to connect
{
echo "Server is down";
}
else
{
echo "Server is up";
if ($x)
{
@fclose($x); //close connection
}
}
}
}
?>
24-Jan-2007 05:01
The following function performs pop3 authentication. Returns NULL on error, or true/false to indicate username/password matching:
$address is the hostname of the server and $ssl is a boolean that indicates whether an SSL connection is requested.
<?php
function pop3authCheck($username, $password, $address, $ssl)
{
if ($ssl)
$uri="ssl://$address:995";
else
$uri="tcp://$address:110";
$fp=fsockopen($uri);
if (!$fp)
return(NULL);
$st=fgets($fp, 512);
if (substr($st, 0, 3)!="+OK")
{
fclose($fp);
return(NULL);
}
$st="USER $username\n";
if (fwrite($fp, $st)!=strlen($st))
{
fclose($fp);
return(NULL);
}
$st=fgets($fp, 512);
if (substr($st, 0, 3)!="+OK")
{
fclose($fp);
return(NULL);
}
$st="PASS $password\n";
if (fwrite($fp, $st)!=strlen($st))
{
<