note:
the default protocol - if not given - seems to be tcp://
fsockopen
(PHP 4, PHP 5)
fsockopen — Open Internet or Unix domain socket connection
Description
Initiates a socket connection to the resource specified by hostname .
PHP supports targets in the Internet and Unix domains as described in List of Supported Socket Transports. A list of supported transports can also be retrieved using stream_get_transports().
The socket will by default be opened in blocking mode. You can switch it to non-blocking mode by using stream_set_blocking().
Parameters
- hostname
-
If you have compiled in OpenSSL support, you may prefix the hostname with either ssl:// or tls:// to use an SSL or TLS client connection over TCP/IP to connect to the remote host.
- port
-
The port number.
- errno
-
If provided, holds the system level error number that occurred in the system-level connect() call.
If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the connect() call. This is most likely due to a problem initializing the socket.
- errstr
-
The error message as a string.
- timeout
-
The connection timeout, in seconds.
Note: If you need to set a timeout for reading/writing data over the socket, use stream_set_timeout(), as the timeout parameter to fsockopen() only applies while connecting the socket.
Return Values
fsockopen() returns a file pointer which may be used together with the other file functions (such as fgets(), fgetss(), fwrite(), fclose(), and feof()). If the call fails, it will return FALSE
Errors/Exceptions
Throws E_WARNING if hostname is not a valid domain.
Changelog
| Version | Description |
|---|---|
| 4.3.0 | Added support for the timeout parameter on win32. |
| 4.3.0 | SSL and TLS over TCP/IP support was added. |
| 4.0.0 | UDP support was added. |
Examples
Example #1 fsockopen() Example
<?php
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
?>
Example #2 Using UDP connection
The example below shows how to retrieve the day and time from the UDP service "daytime" (port 13) in your own machine.
<?php
$fp = fsockopen("udp://127.0.0.1", 13, $errno, $errstr);
if (!$fp) {
echo "ERROR: $errno - $errstr<br />\n";
} else {
fwrite($fp, "\n");
echo fread($fp, 26);
fclose($fp);
}
?>
Notes
Note: Depending on the environment, the Unix domain or the optional connect timeout may not be available.
UDP sockets will sometimes appear to have opened without an error, even if the remote host is unreachable. The error will only become apparent when you read or write data to/from the socket. The reason for this is because UDP is a "connectionless" protocol, which means that the operating system does not try to establish a link for the socket until it actually needs to send or receive data.
Note: When specifying a numerical IPv6 address (e.g. fe80::1), you must enclose the IP in square brackets—for example, tcp://[fe80::1]:80.
See Also
- pfsockopen() - Open persistent Internet or Unix domain socket connection
- stream_set_blocking() - Set blocking/non-blocking mode on a stream
- stream_set_timeout() - Set timeout period on a stream
- fgets() - Gets line from file pointer
- fgetss() - Gets line from file pointer and strip HTML tags
- fwrite() - Binary-safe file write
- fclose() - Closes an open file pointer
- feof() - Tests for end-of-file on a file pointer
- The Curl extension
fsockopen
22-Jun-2009 12:20
21-Jun-2009 10:17
When downloading large files, it is not really efficient to put the whole server answer in memory before parsing the data to remove the header parts. Here is a simple way to do it while writing the data as it arrive:
<?php
// $socket is a valid fsockopen handle
$out = '';
$headerendfound = false;
$fp = fopen($fileTarget, 'w');
$buffer = '';
while (!feof($socket)) {
$out = fgets ($socket,16384);
if ($headerendfound) {
fwrite($fp, $out);
print '.';
}
if (!$headerendfound) {
$buffer .= $out;
print "searching for header\n";
$headerend = strpos($buffer, "\r\n\r\n");
if ($headerend !== false) {
$headerendfound = true;
fwrite($fp, substr($buffer, $headerend+4));
$buffer = '';
}
}
}
fclose($fp);
fclose($socket);
?>
16-Jun-2009 08:15
look at this smart ssl/http fsockopen function as a good solution for dealing with things
<?php
function _get($type,$host,$port='80',$path='/',$data='') {
$_err = 'lib sockets::'.__FUNCTION__.'(): ';
switch($type) { case 'http': $type = ''; case 'ssl': continue; default: die($_err.'bad $type'); } if(!ctype_digit($port)) die($_err.'bad port');
if(!empty($data)) foreach($data AS $k => $v) $str .= urlencode($k).'='.urlencode($v).'&'; $str = substr($str,0,-1);
$fp = fsockopen($host,$port,$errno,$errstr,$timeout=30);
if(!$fp) die($_err.$errstr.$errno); else {
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ".strlen($str)."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $str."\r\n\r\n");
while(!feof($fp)) $d .= fgets($fp,4096);
fclose($fp);
} return $d;
}
?>
29-Apr-2009 01:45
I've been searching a big while before considering that it was impossible to use context with fsockopen, as it was in PHP4.
If you want to use sockets with tls or ssl encryption and certificates and so on, you'd better have a look to stream_socket_client.
21-Nov-2008 06:42
To just take the HTTP content from fsockopen, better wait until feof finish to read the \r\n separator
<?php
//fsockopen, fputs..
$content = "";
$header = "not yet";
while( !feof( $pointer ) ) {
$line = fgets( $pointer, 128 );
if( $line == "\r\n" && $header == "not yet" ) {
$header = "passed";
}
if( $header == "passed" ) {
$content .= $line;
}
}
//fclose..
echo( substr( $content, 2 ) );
?>
06-Nov-2008 11:17
[NOTE BY danbrown AT php DOT net: Updated version. Contains author-submitted bug fixes.]
Here is a way to get an array of cities / states for any zip code anywhere in the US. This example uses a $_GET variable to specify which zip code, but you can get it from any source you wish. This will return actual and acceptable zip code cities (according to USPS), but can be easily modified to include just the actual city.
<?php
if($_GET['zip'])
{
if(!($fp = fsockopen('zip4.usps.com', 80, $errno, $errstr)))
echo 'Could not connect to USPS! Error number: ' . $errno . '(' . $errstr . ')';
else
{
$poststring =
"GET /zip4/zcl_3_results.jsp?zip5=" . $_GET['zip'] . " HTTP/1.0\r\n" .
"Connection: close\r\n\r\n";
fputs($fp, $poststring);
$buffer = '';
while(!feof($fp))
$buffer .= fgets($fp, 128);
fclose($fp);
preg_match('/Actual City name(.*)/s', $buffer, $match);
$temp = explode('Not Acceptable', $match[1]);
// Capture city/state combination for all valid cities
preg_match_all('/headers="pre">(?:<b>)?([\w|\s]+), (\w+)/', $temp[0], $acceptable, PREG_SET_ORDER);
$values = array();
foreach($acceptable as $value)
$values[] =
array
(
'city' => $value[1],
'state' => $value[2]
);
if(count($values) == 0)
echo 'Zip could not be found in the database!';
}
}
else
echo 'Please specify a zip!';
?>
29-Oct-2008 01:04
For those wanting to use fsockopen() to connect to a local UNIX socket who can't find documentation on how to do it, here's a (rough) example:
<?php
$sock = fsockopen('unix:///full/path/to/my/socket.sock', NULL, $errno, $errstr);
fwrite($sock, 'SOME COMMAND'."\r\n");
echo fread($sock, 4096)."\n";
fclose($sock);
?>
26-Oct-2008 11:30
When you're connecting through a proxy server you can't rely on fsockopen returning false to indicate that the connection has failed. (This also applies to fgets and fwrite.)
To check whether the proxy succeeded in contacting the real target host, you need to look for the http response code in the headers that get returned. Typically, if the proxy was unable to reach the host, you'll find a line containing something like:
HTTP/1.0 503 Service Unavailable
12-Oct-2008 12:26
"system level connect()" is not further documented inside the php documentation so it is hard to find out more about error numbers.
someone suggest a more system-close way to find out more about error numbers here: http://www.askapache.com/php/fsockopen-socket.html (an interesting read about fsockopen anyway).
in my case i could debug to the fact that fsocketopen error number 16 was resulted in the inpossibility to resolve a hostname.
09-Sep-2008 03:28
Notice using "tcp" insted of "http"
<?php
fsockopen("tcp://example.net",80 , $errno, $errstr, 30);
?>
06-Sep-2008 04: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;
}
?>
21-Jul-2008 12: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. :-)
17-Apr-2008 01:21
If you have to use a proxy to make requests outside of your local network, you may use this class:
<?php
/*
*
* No Proxy Authentification Implemented; PHP 5
*
*/
class RemoteFopenViaProxy {
private $result;
private $proxy_name;
private $proxy_port;
private $request_url;
public function get_proxy_name() {
return $this->proxy_name;
}
public function set_proxy_name($n) {
$this->proxy_name = $n;
}
public function get_proxy_port() {
return $this->proxy_port;
}
public function set_proxy_port($p) {
$this->proxy_port = $p;
}
public function get_request_url() {
return $this->request_url;
}
public function set_request_url($u) {
$this->request_url = $u;
}
public function get_result() {
return $this->result;
}
public function set_result($r) {
$this->result = $r;
}
private function get_url_via_proxy() {
$proxy_fp = fsockopen($this->get_proxy_name(), $this->get_proxy_port());
if (!$proxy_fp) {
return false;
}
fputs($proxy_fp, "GET " . $this->get_request_url() . " HTTP/1.0\r\nHost: " . $this->get_proxy_name() . "\r\n\r\n");
while (!feof($proxy_fp)) {
$proxy_cont .= fread($proxy_fp, 4096);
}
fclose($proxy_fp);
$proxy_cont = substr($proxy_cont, strpos($proxy_cont, "\r\n\r\n") + 4);
return $proxy_cont;
}
private function get_url($url) {
$fd = @ file($url);
if ($fd) {
return $fd;
} else {
return false;
}
}
private function logger($line, $file) {
$fd = fopen($file . ".log", "a+");
fwrite($fd, date("Ymd G:i:s") . " - " . $file . " - " . $line . "\n");
fclose($fd);
}
function __construct($url, $proxy_name = "", $proxy_port = "") {
$this->set_request_url($url);
$this->set_proxy_name($proxy_name);
$this->set_proxy_port($proxy_port);
}
public function request_via_proxy() {
$this->set_result($this->get_url_via_proxy());
if (!$this->get_result()) {
$this->logger("FAILED: get_url_via_proxy(" . $this->get_proxy_name() . "," . $this->get_proxy_port() . "," . $this->get_request_url() . ")", "RemoteFopenViaProxyClass.log");
}
}
public function request_without_proxy() {
$this->set_result($this->get_url($this->get_request_url()));
if (!$this->get_result()) {
$this->logger("FAILED: get_url(" . $url . ")", "RemoteFopenViaProxyClass.log");
}
}
}
?>
Use it this way:
<?php
// call constructor
$obj = new RemoteFopenViaProxy($insert_request_url, $insert_proxy_name, $insert_proxy_port);
// change settings after object generation
$obj->set_proxy_name($insert_proxy_name);
$obj->set_proxy_port($insert_proxy_port);
$obj->set_request_url($insert_request_url);
$obj->request_via_proxy();
echo $obj->get_result();
?>
If there are errors during execution, the script tries to write some useful information into a log file.
08-Mar-2008 03: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 05: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-Sep-2007 01:34
The DEFAULT stream timeout is set according to default_socket_timeout in your php.ini file. Took forever for me to dig that up....
04-Aug-2007 08:32
For those of you who do not have cURL, you might want to try this.
It doesn't have all the functions that cURL has, but it has the basics.
Please let me know of any bugs or problems.
<?php
function open_page($url,$f=1,$c=2,$r=0,$a=0,$cf=0,$pd=""){
global $oldheader;
$url = str_replace("http://","",$url);
if (preg_match("#/#","$url")){
$page = $url;
$url = @explode("/",$url);
$url = $url[0];
$page = str_replace($url,"",$page);
if (!$page || $page == ""){
$page = "/";
}
$ip = gethostbyname($url);
}else{
$ip = gethostbyname($url);
$page = "/";
}
$open = fsockopen($ip, 80, $errno, $errstr, 60);
if ($pd){
$send = "POST $page HTTP/1.0\r\n";
}else{
$send = "GET $page HTTP/1.0\r\n";
}
$send .= "Host: $url\r\n";
if ($r){
$send .= "Referer: $r\r\n";
}else{
if ($_SERVER['HTTP_REFERER']){
$send .= "Referer: {$_SERVER['HTTP_REFERER']}\r\n";
}
}
if ($cf){
if (@file_exists($cf)){
$cookie = urldecode(@file_get_contents($cf));
if ($cookie){
$send .= "Cookie: $cookie\r\n";
$add = @fopen($cf,'w');
fwrite($add,"");
fclose($add);
}
}
}
$send .= "Accept-Language: en-us, en;q=0.50\r\n";
if ($a){
$send .= "User-Agent: $a\r\n";
}else{
$send .= "User-Agent: {$_SERVER['HTTP_USER_AGENT']}\r\n";
}
if ($pd){
$send .= "Content-Type: application/x-www-form-urlencoded\r\n";
$send .= "Content-Length: " .strlen($pd) ."\r\n\r\n";
$send .= $pd;
}else{
$send .= "Connection: Close\r\n\r\n";
}
fputs($open, $send);
while (!feof($open)) {
$return .= fgets($open, 4096);
}
fclose($open);
$return = @explode("\r\n\r\n",$return,2);
$header = $return[0];
if ($cf){
if (preg_match("/Set\-Cookie\: /i","$header")){
$cookie = @explode("Set-Cookie: ",$header,2);
$cookie = $cookie[1];
$cookie = explode("\r",$cookie);
$cookie = $cookie[0];
$cookie = str_replace("path=/","",$cookie[0]);
$add = @fopen($cf,'a');
fwrite($add,$cookie,strlen