FREE THOUGHT · FREE SOFTWARE · FREE WORLD

Home  »  PHP  »  Fsockopen Magic

by 9 comments

Fsockopen PowerPHP's function fsockopen lets you open an Internet or Unix domain socket connection for connecting to a resource, and is one of the most powerful functions. fsockopen could be described as creating a direct link to the wire connected to a resource, which means you can send any information (EBCDIC, ASCII, Hex, C arrays, Raw) directly to the target server.

A Socket is like /dev/null

In unix you can send anything to the /dev/null device, for Windows think Recycle Bin, and likewise you can send anything to a socket created with fsockopen. Just like # cat file > /dev/null I've seen fsockopen code that sends custom exploits to cisco routers, including being used by the metasploit framework. I've seen fsockopen telnet emulation, smtp/pop3 login, and a lot of other advanced raw networking that is exciting for me see.

Some Definitions for Fsockopen

client
A program that establishes connections for the purpose of sending requests.
server
An application program that accepts connections in order to service requests by sending back responses.

Simple Socket Explantion

A web server host listens on TCP port 80. When a client host wishes to view a resource on the web server, it establishes a TCP connection with the server host by opening a socket to send the request for the resource. When the connection is established, the client and server exchange requests and responses (respectively) until the connection is closed or aborted.

Why use fsockopen?

SPEED! Fsockopen is the lowest php helper function to create and use a socket. Once you have a socket opened you can read/write data over that socket using binary-safe php functions like fwrite and fread very quickly.

For example, the PHP function gethostbyaddr gets the reverse DNS associated with an IP address, and gethostbyname does the reverse getting the IP address associated with a DNS record/website. But like most PHP helper networking functions they are designed to be robust. This means they tie into your OS internals to check your resolver settings, have long timeouts to make sure they don't miss a slow host, and are really quite bloated in order to be so robust and work for every situation. By using fsockopen as I show here: PHP fsockopen for FAST DNS lookups over UDP, it's literally just opening a single socket to the DNS server over UDP, sending the request, and shows the response. The speed boost goes from upwards of 50 seconds the normal way, to a max of just 5 seconds in that example. When doing many many lookups or async lookups (such as looking up the reverse ips for thousands of addresses), the speed boost is 30-1000x faster using straight fsockopen.

HTTP and fsockopen

Snoopy Fsockopen HTTP Class for PHPThe Snoopy class is bundled with WordPress distributions and uses fsockopen to achieve most of its cool features, it's not used as much by WP now since WP has a newer and much better/complicated replacement, but it's an excellent small but of code that illustrates fsockopen use. Many WordPress core, plugins, and other included files and classes also use the fsockopen function to communicate via Sockets.

Fsockopen Examples

fsockopen warningNote the warning sign, fsockopen is dangerous in the sense that you can crash your server, perform a DOS against your own server or other site, use up all your servers available sockets and fd descriptors, use up your bandwidth, etc.. Shouldn't be a problem unless you are being malicious or careless.

Here are some BOSS fsockopen functions I hacked together yesterday for use in my AskApache Crazy Cache WordPress Plugin. I've used code and ideas from 100's of authors, projects, and docs to try to make this the very best I can.

Intro

This is a working example employing as many of the best-practices, tips, and tricks for using fsockopen on remote streams that I could find.


// max time for script execution
!defined('AA_MAX_TIME') && define('AA_MAX_TIME',  60);

// max time for socket reads
!defined('AA_RECV_TIME') && define('AA_RECV_TIME', 30);

// max time for socket connect
!defined('AA_CONN_TIME') && define('AA_CONN_TIME', 5);

// linebreak
!defined('AA_LF') && define('AA_LF', chr(13).chr(10));



// ignore TCP RST i.e. browser stop button
@ignore_user_abort(1);

// set the script execution time
@set_time_limit(AA_MAX_TIME);

// set the default socket timeout value
@ini_set("default_socket_timeout",AA_RECV_TIME);

// output implicitly
@ob_implicit_flush(1);

// for binary freads
@set_magic_quotes_runtime(0);

// keep track of script execution time
$aa_time=time();


// download each of these urls using fsockopen
aa_dl('http://httpd.apache.org');
aa_dl('http://www.w3.org');
aa_dl('http://www.google.com');
aa_dl('http://www.freebsd.org/cgi/man.cgi?query=connect&sektion=2&apropos=0&manpath=FreeBSD+7.0-RELEASE');
aa_dl('http://www.askapache.com/htaccess/htaccess.html');
aa_dl('http://www.php.net');
aa_dl('http://en.wikipedia.org/wiki/Main_Page');



/*  returns a socket pointer if valid or displays an error message
    sets stream timeout, starts the clock to check for socket read time */
function askapache_get_sock($target,$port){
  global $aa_time_start;
  $aa_time_start=time();
  if(false===($fp = @fsockopen($target,$port,$errno,$errstr,AA_CONN_TIME))||!is_resource($fp))
  	return askapache_sock_strerror($errno,$errstr);
  @stream_set_timeout($fp, AA_RECV_TIME);
  return $fp;
}




/*  writes request, then reads response until EOF, script max, or socket max
    returns response on success.  Uses buffer to allow size>100megs */
function askapache_txrx($fp,$request,$chunk=1024){
  $rec=$buf='';
  if(!@fwrite($fp, $request, strlen($request)))die('fwrite error');
  while ( !@feof($fp) && askapache_time_ok(askapache_time_passed())){
    $buf = @fread($fp, $chunk);
    $rec .= $buf;
  }
  if(!@fclose($fp))die('fclose error');
  return $rec;
}


/* initiates the socket and download for the passed url.
   automatically handles gzip, chunked, both, and plain downloads.
   uses the long2ip/ip2long for ip validation, uses gethostbyname to
   get the ipv4 address which saves fsockopen from having to do the lookup
   final data is saved to $rbody but currently only displays headers.*/
function aa_dl($url=NULL){
  global $aa_time;
  $ub = @parse_url($url);
  if(!isset($ub['host'])||empty($ub['host'])) die("bad url $url");
  $proto 	= ($ub['scheme']=='https')?'ssl://':'';
  $port 	= (isset($ub['port'])&&!empty($ub['port'])) ? $ub['port']:(($proto!='')?443:80);
  $path 	= (isset($ub['path'])&&!empty($ub['path'])) ? $ub['path']:'/';
  $query 	= (isset($ub['query'])&&!empty($ub['query'])) ? '?'.$ub['query'] : '';
  $host 	= $ub['host'];
  $ipp 		= @gethostbyname($host);
  $ip 		= ($ipp!=$host) ? long2ip(ip2long($ipp)) : $host;

  $headers=array(
   "GET {$path}{$query} HTTP/1.1",
   "Host: {$host}",
   'User-Agent: Mozilla/5.0 (AskApache/; +http://www.askapache.com/)',
   'Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,*/*;q=0.5',
   'Accept-Language: en-us,en;q=0.5',
   'Accept-Encoding: gzip,deflate',
   'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7',
   'Connection: close','Referer: http://www.askapache.com'
  );
  $request=join(AA_LF,$headers).AA_LF.AA_LF;

  $fp=askapache_get_sock($proto.$ip, $port);
  if($fp){
    $rbody=$rec='';$resp_headers=array();
    $rec=askapache_txrx($fp,$request);
    list($resp_headers, $rbody) = explode(AA_LF.AA_LF, trim($rec), 2);
	echo "n

$request

n

$resp_headers

n"; $gzip2=(stripos($resp_headers,'Content-Encoding')!==false && stripos($resp_headers,'gzip')!==false)?1:0; $chunk=(stripos($resp_headers,'Transfer-Encoding')!==false && stripos($resp_headers,'chunked')!==false)?1:0; $rbody=aa_decode_body($rbody,$chunk,$gzip2); unset($rbody); } } /* based on http://us.php.net/manual/en/function.fsockopen.php#75175 ungzips and/or re-assembles transfer-encoded:chunked responses returns the good response on success */ function aa_decode_body ($str, $chunked, $gzipped){ if($gzipped && !$chunked) return aa_gzdecode($str); if(!$gzipped && !$chunked) return $str; $tmp = $str; $str = ''; do { $tmp = ltrim($tmp); $pos = strpos($tmp,AA_LF); $len = hexdec(substr($tmp, 0, $pos)); if($gzipped) $str .= gzinflate(substr($tmp,($pos+12),$len)); else $str .=substr($tmp,($pos+2),$len); $tmp = substr($tmp,($len+$pos+2)); $chk=trim($tmp); } while (!empty($chk)); return $str; } /* based on http://us2.php.net/manual/en/function.gzencode.php#82520 saves the gzipped data to a tempfile, then outputs the decoded data to the output buffer using readgzfile, returning the decoded buffer and deleting the tempfile on success */ function aa_gzdecode($data){ $g=tempnam('/tmp','ff'); @file_put_contents($g,$data); ob_start(); readgzfile($g); $d=ob_get_clean(); @unlink($g); return $d; } /* very cool! this is run during socket reads and checks whether the script execution time limit or the socket read time limit has been met, killing the script if so, otherwise returns true. Run with a cron-like process */ function askapache_time_ok($sock_time=0) { global $aa_time; if (time()-$aa_time>AA_MAX_TIME) die('killed script.. time exceeded '.AA_MAX_TIME.' Total: '.$total); if ($sock_time>AA_RECV_TIME) die('Killed socket.. time exceeded '.AA_RECV_TIME.' Total: '.$sock_time); return true; } /* input for askapache_time_ok to keep track of each socket read time time. */ function askapache_time_passed() { global $aa_time_start; return (time() - $aa_time_start); } /* handles fsockopen errors, printing them out though you may want to die on err */ function askapache_sock_strerror($errno,$errstr){ switch($errno){ case -3: $err="Socket creation failed"; break; case -4: $err="DNS lookup failure"; break; case -5: $err="Connection refused or timed out"; break; case 104: $err="Connection reset by client"; break; case 110: $err="Connection timed out"; break; case 111: $err="Connection refused"; break; case 113: $err="No route to host"; break; default: $err="Connection failed"; break; } echo '

Fsockopen failed!'."n[".$errno."] ".$err." (".$errstr.")

"; return false; }

Debugging Fsockopen

If you really want to know more about fsockopen, you can do what I did and read all the relevant php source files, your OS sys, lib, and user files relevant to fsockopen, and of course you can always trace php using the fsockopen function to get an under-the-hood look at what in the world fsockopen is doing. Personally, I was trying to find more error codes and error strings to display when an fsockopen call failed, and I ended up finding over 50..

fsockopen Errors

function fsockopen_err($errnum)
{
   static $fsockopen_errors;
   if ( is_null($fsockopen_errors) ) {
     $fsockopen_errors = array(
	0 => 'Success',
	1 => 'Operation not permitted',
	2 => 'No such file or directory',
	3 => 'No such process',
	4 => 'Interrupted system call - DNS lookup failure',
	5 => 'Input/output error - Connection refused or timed out',
	6 => 'No such device or address',
	7 => 'Argument list too long',
	8 => 'Exec format error',
	9 => 'Bad file descriptor',
	10 => 'No child processes',
	11 => 'Resource temporarily unavailable',
	12 => 'Cannot allocate memory',
	13 => 'Permission denied',
	14 => 'Bad address',
	15 => 'Block device required',
	16 => 'Device or resource busy',
	17 => 'File exists',
	18 => 'Invalid cross-device link',
	19 => 'No such device',
	20 => 'Not a directory',
	21 => 'Is a directory',
	22 => 'Invalid argument',
	23 => 'Too many open files in system',
	24 => 'Too many open files',
	25 => 'Inappropriate ioctl for device',
	26 => 'Text file busy',
	27 => 'File too large',
	28 => 'No space left on device',
	29 => 'Illegal seek',
	30 => 'Read-only file system',
	31 => 'Too many links',
	32 => 'Broken pipe',
	33 => 'Numerical argument out of domain',
	34 => 'Numerical result out of range',
	35 => 'Resource deadlock avoided',
	36 => 'File name too long',
	37 => 'No locks available',
	38 => 'Function not implemented',
	39 => 'Directory not empty',
	40 => 'Too many levels of symbolic links',
	41 => 'Unknown error 41',
	42 => 'No message of desired type',
	43 => 'Identifier removed',
	44 => 'Channel number out of range',
	45 => 'Level 2 not synchronized',
	46 => 'Level 3 halted',
	47 => 'Level 3 reset',
	48 => 'Link number out of range',
	49 => 'Protocol driver not attached',
	50 => 'No CSI structure available',
	51 => 'Level 2 halted',
	52 => 'Invalid exchange',
	53 => 'Invalid request descriptor',
	54 => 'Exchange full',
	55 => 'No anode',
	56 => 'Invalid request code',
	57 => 'Invalid slot',
	58 => 'Unknown error 58',
	59 => 'Bad font file format',
	60 => 'Device not a stream',
	61 => 'No data available',
	62 => 'Timer expired',
	63 => 'Out of streams resources',
	64 => 'Machine is not on the network',
	65 => 'Package not installed',
	66 => 'Object is remote',
	67 => 'Link has been severed',
	68 => 'Advertise error',
	69 => 'Srmount error',
	70 => 'Communication error on send',
	71 => 'Protocol error',
	72 => 'Multihop attempted',
	73 => 'RFS specific error',
	74 => 'Bad message',
	75 => 'Value too large for defined data type',
	76 => 'Name not unique on network',
	77 => 'File descriptor in bad state',
	78 => 'Remote address changed',
	79 => 'Can not access a needed shared library',
	80 => 'Accessing a corrupted shared library',
	81 => '.lib section in a.out corrupted',
	82 => 'Attempting to link in too many shared libraries',
	83 => 'Cannot exec a shared library directly',
	84 => 'Invalid or incomplete multibyte or wide character',
	85 => 'Interrupted system call should be restarted',
	86 => 'Streams pipe error',
	87 => 'Too many users',
	88 => 'Socket operation on non-socket',
	89 => 'Destination address required',
	90 => 'Message too long',
	91 => 'Protocol wrong type for socket',
	92 => 'Protocol not available',
	93 => 'Protocol not supported',
	94 => 'Socket type not supported',
	95 => 'Operation not supported',
	96 => 'Protocol family not supported',
	97 => 'Address family not supported by protocol',
	98 => 'Address already in use',
	99 => 'Cannot assign requested address',
	100 => 'Network is down',
	101 => 'Network is unreachable',
	102 => 'Network dropped connection on reset',
	103 => 'Software caused connection abort',
	104 => 'Connection reset by peer',
	105 => 'No buffer space available',
	106 => 'Transport endpoint is already connected',
	107 => 'Transport endpoint is not connected',
	108 => 'Cannot send after transport endpoint shutdown',
	109 => 'Too many references: cannot splice',
	110 => 'Connection timed out',
	111 => 'Connection refused',
	112 => 'Host is down',
	113 => 'No route to host',
	114 => 'Operation already in progress',
	115 => 'Operation now in progress',
	116 => 'Stale NFS file handle',
	117 => 'Structure needs cleaning',
	118 => 'Not a XENIX named type file',
	119 => 'No XENIX semaphores available',
	120 => 'Is a named type file',
	121 => 'Remote I/O error',
	122 => 'Disk quota exceeded',
	123 => 'No medium found',
	124 => 'Wrong medium type',
	125 => 'Operation canceled',
	126 => 'Required key not available',
	127 => 'Key has expired',
	128 => 'Key has been revoked',
	129 => 'Key was rejected by service',
	130 => 'Owner died',
	131 => 'State not recoverable',
	132 => 'Operation not possible due to RF-kill',
	133 => 'Memory page has hardware error'
      );
    }
    return ( isset( $fsockopen_errors[ $errnum ] ) ) ? $fsockopen_errors[ $errnum ] : $errnum;
}

If you would like to see all the errors on your particular machine:

for ( $i=-50, $s=""; ( $i<250 && !!$s=socket_strerror($i) ); $i++ ) {
   !!! strpos( $s, 'nknown error' ) && print "$i => $s\n";
}

Which outputs:

0 => Success
1 => Operation not permitted
2 => No such file or directory
3 => No such process
4 => Interrupted system call
5 => Input/output error
6 => No such device or address
7 => Argument list too long
8 => Exec format error
9 => Bad file descriptor
10 => No child processes
11 => Resource temporarily unavailable
12 => Cannot allocate memory
13 => Permission denied
14 => Bad address
15 => Block device required
16 => Device or resource busy
17 => File exists
18 => Invalid cross-device link
19 => No such device
20 => Not a directory
21 => Is a directory
22 => Invalid argument
23 => Too many open files in system
24 => Too many open files
25 => Inappropriate ioctl for device
26 => Text file busy
27 => File too large
28 => No space left on device
29 => Illegal seek
30 => Read-only file system
31 => Too many links
32 => Broken pipe
33 => Numerical argument out of domain
34 => Numerical result out of range
35 => Resource deadlock avoided
36 => File name too long
37 => No locks available
38 => Function not implemented
39 => Directory not empty
40 => Too many levels of symbolic links
42 => No message of desired type
43 => Identifier removed
44 => Channel number out of range
45 => Level 2 not synchronized
46 => Level 3 halted
47 => Level 3 reset
48 => Link number out of range
49 => Protocol driver not attached
50 => No CSI structure available
51 => Level 2 halted
52 => Invalid exchange
53 => Invalid request descriptor
54 => Exchange full
55 => No anode
56 => Invalid request code
57 => Invalid slot
59 => Bad font file format
60 => Device not a stream
61 => No data available
62 => Timer expired
63 => Out of streams resources
64 => Machine is not on the network
65 => Package not installed
66 => Object is remote
67 => Link has been severed
68 => Advertise error
69 => Srmount error
70 => Communication error on send
71 => Protocol error
72 => Multihop attempted
73 => RFS specific error
74 => Bad message
75 => Value too large for defined data type
76 => Name not unique on network
77 => File descriptor in bad state
78 => Remote address changed
79 => Can not access a needed shared library
80 => Accessing a corrupted shared library
81 => .lib section in a.out corrupted
82 => Attempting to link in too many shared libraries
83 => Cannot exec a shared library directly
84 => Invalid or incomplete multibyte or wide character
85 => Interrupted system call should be restarted
86 => Streams pipe error
87 => Too many users
88 => Socket operation on non-socket
89 => Destination address required
90 => Message too long
91 => Protocol wrong type for socket
92 => Protocol not available
93 => Protocol not supported
94 => Socket type not supported
95 => Operation not supported
96 => Protocol family not supported
97 => Address family not supported by protocol
98 => Address already in use
99 => Cannot assign requested address
100 => Network is down
101 => Network is unreachable
102 => Network dropped connection on reset
103 => Software caused connection abort
104 => Connection reset by peer
105 => No buffer space available
106 => Transport endpoint is already connected
107 => Transport endpoint is not connected
108 => Cannot send after transport endpoint shutdown
109 => Too many references: cannot splice
110 => Connection timed out
111 => Connection refused
112 => Host is down
113 => No route to host
114 => Operation already in progress
115 => Operation now in progress
116 => Stale file handle
117 => Structure needs cleaning
118 => Not a XENIX named type file
119 => No XENIX semaphores available
120 => Is a named type file
121 => Remote I/O error
122 => Disk quota exceeded
123 => No medium found
124 => Wrong medium type
125 => Operation canceled
126 => Required key not available
127 => Key has expired
128 => Key has been revoked
129 => Key was rejected by service
130 => Owner died
131 => State not recoverable
132 => Operation not possible due to RF-kill
133 => Memory page has hardware error

Tracing fsockopen using Strace

Once you save the above file on your site, you can use the strace tool to debug it. This is a tad overboard but way cool nevertheless!

strace -e trace=connect php -nef fsockopen-test.php

connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("66.33.216.129")}, 28) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("192.87.106.226")}, 16) = -1 EINPROGRESS (Operation now in progress)

strace -e trace=network php -nef fsockopen-test.php

socket(PF_FILE, SOCK_STREAM, 0)         = 3
connect(3, {sa_family=AF_FILE, path="/var/run/.nscd_socket"}, 110) = -1 ENOENT (No such file or directory)
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("66.33.216.129")}, 28) = 0
send(3, "2742211??1??????5httpd6apache3org??1"..., 34, 0) = 34
recvfrom(3, "274221201200?1?1????5httpd6apache3org?"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("66.33.216.129")}, [16]) = 50
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = -1 EAFNOSUPPORT (Address family not supported by protocol)
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("192.87.106.226")}, 16) = -1 EINPROGRESS (Operation now in progress)
getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
send(3, "GET / HTTP/1.1rnHost: httpd.apac"..., 356, MSG_DONTWAIT) = 356
recv(3, "HTTP/1.1 200 OKrnDate: Wed, 02 J"..., 8192, MSG_DONTWAIT) = 2609
recv(3, "", 8192, MSG_DONTWAIT)         = 0

strace -q -e trace=all php -nef fsockopen-test.php

mmap2(NULL, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76ba000
munmap(0xb76ba000, 266240)              = 0
socket(PF_FILE, SOCK_STREAM, 0)         = 3
connect(3, {sa_family=AF_FILE, path="/var/run/.nscd_socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
open("/etc/hosts", O_RDONLY)            = 3
fcntl64(3, F_GETFD)                     = 0
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=948, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f6e000
read(3, "# /etc/hosts - dh2 generatedn127"..., 4096) = 948
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb7f6e000, 4096)                = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("66.33.216.129")}, 28) = 0
send(3, "X~1??1??????2entwikipedia3org??1"..., 34, 0) = 34
gettimeofday({1214998196, 656179}, NULL) = 0
poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 5000) = 1
ioctl(3, FIONREAD, [100])               = 0
recvfrom(3, "X~201200?1?3????2entwikipedia3org??1"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("66.33.216.129")}, [16]) = 100
close(3)                                = 0
time(NULL)                              = 1214998196
gettimeofday({1214998196, 656754}, NULL) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
fcntl64(3, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(3, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("208.80.152.2")}, 16) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 10000) = 1
getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
fcntl64(3, F_SETFL, O_RDWR)             = 0
send(3, "GET /wiki/Main_Page HTTP/1.1rnHo"..., 370, MSG_DONTWAIT) = 370
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0
time(NULL)                              = 1214998196
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP, revents=POLLIN}], 1, 30000) = 1
recv(3, "HTTP/1.0 200 OKrnDate: Wed, 02 J"..., 8192, MSG_DONTWAIT) = 2896
time(NULL)                              = 1214998196
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP, revents=POLLIN}], 1, 30000) = 1
recv(3, "214!337i30733623w253wy21526EL227;227253261"..., 8192, MSG_DONTWAIT) = 5792
time(NULL)                              = 1214998196
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP, revents=POLLIN}], 1, 30000) = 1
recv(3, "420127321417yI347257371373344332330227245"..., 8192, MSG_DONTWAIT) = 7487
time(NULL)                              = 1214998197
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP, revents=POLLIN}], 1, 30000) = 1
recv(3, "", 8192, MSG_DONTWAIT)         = 0
close(3)                                = 0
write(1, "n
GET /wiki/Main_Page HTTP/1"..., 1300

More Fsockopen Info

Fsockopen Related Links

Fsockopen Practical Uses

Socket Constants

define ('SOCKET_EPERM', 1);
define ('SOCKET_ENOENT', 2);
define ('SOCKET_EINTR', 4);
define ('SOCKET_EIO', 5);
define ('SOCKET_ENXIO', 6);
define ('SOCKET_E2BIG', 7);
define ('SOCKET_EBADF', 9);
define ('SOCKET_EAGAIN', 11);
define ('SOCKET_ENOMEM', 12);
define ('SOCKET_EACCES', 13);
define ('SOCKET_EFAULT', 14);
define ('SOCKET_ENOTBLK', 15);
define ('SOCKET_EBUSY', 16);
define ('SOCKET_EEXIST', 17);
define ('SOCKET_EXDEV', 18);
define ('SOCKET_ENODEV', 19);
define ('SOCKET_ENOTDIR', 20);
define ('SOCKET_EISDIR', 21);
define ('SOCKET_EINVAL', 22);
define ('SOCKET_ENFILE', 23);
define ('SOCKET_EMFILE', 24);
define ('SOCKET_ENOTTY', 25);
define ('SOCKET_ENOSPC', 28);
define ('SOCKET_ESPIPE', 29);
define ('SOCKET_EROFS', 30);
define ('SOCKET_EMLINK', 31);
define ('SOCKET_EPIPE', 32);
define ('SOCKET_ENAMETOOLONG', 36);
define ('SOCKET_ENOLCK', 37);
define ('SOCKET_ENOSYS', 38);
define ('SOCKET_ENOTEMPTY', 39);
define ('SOCKET_ELOOP', 40);
define ('SOCKET_EWOULDBLOCK', 11);
define ('SOCKET_ENOMSG', 42);
define ('SOCKET_EIDRM', 43);
define ('SOCKET_ECHRNG', 44);
define ('SOCKET_EL2NSYNC', 45);
define ('SOCKET_EL3HLT', 46);
define ('SOCKET_EL3RST', 47);
define ('SOCKET_ELNRNG', 48);
define ('SOCKET_EUNATCH', 49);
define ('SOCKET_ENOCSI', 50);
define ('SOCKET_EL2HLT', 51);
define ('SOCKET_EBADE', 52);
define ('SOCKET_EBADR', 53);
define ('SOCKET_EXFULL', 54);
define ('SOCKET_ENOANO', 55);
define ('SOCKET_EBADRQC', 56);
define ('SOCKET_EBADSLT', 57);
define ('SOCKET_ENOSTR', 60);
define ('SOCKET_ENODATA', 61);
define ('SOCKET_ETIME', 62);
define ('SOCKET_ENOSR', 63);
define ('SOCKET_ENONET', 64);
define ('SOCKET_EREMOTE', 66);
define ('SOCKET_ENOLINK', 67);
define ('SOCKET_EADV', 68);
define ('SOCKET_ESRMNT', 69);
define ('SOCKET_ECOMM', 70);
define ('SOCKET_EPROTO', 71);
define ('SOCKET_EMULTIHOP', 72);
define ('SOCKET_EBADMSG', 74);
define ('SOCKET_ENOTUNIQ', 76);
define ('SOCKET_EBADFD', 77);
define ('SOCKET_EREMCHG', 78);
define ('SOCKET_ERESTART', 85);
define ('SOCKET_ESTRPIPE', 86);
define ('SOCKET_EUSERS', 87);
define ('SOCKET_ENOTSOCK', 88);
define ('SOCKET_EDESTADDRREQ', 89);
define ('SOCKET_EMSGSIZE', 90);
define ('SOCKET_EPROTOTYPE', 91);
define ('SOCKET_ENOPROTOOPT', 92);
define ('SOCKET_EPROTONOSUPPORT', 93);
define ('SOCKET_ESOCKTNOSUPPORT', 94);
define ('SOCKET_EOPNOTSUPP', 95);
define ('SOCKET_EPFNOSUPPORT', 96);
define ('SOCKET_EAFNOSUPPORT', 97);
define ('SOCKET_EADDRINUSE', 98);
define ('SOCKET_EADDRNOTAVAIL', 99);
define ('SOCKET_ENETDOWN', 100);
define ('SOCKET_ENETUNREACH', 101);
define ('SOCKET_ENETRESET', 102);
define ('SOCKET_ECONNABORTED', 103);
define ('SOCKET_ECONNRESET', 104);
define ('SOCKET_ENOBUFS', 105);
define ('SOCKET_EISCONN', 106);
define ('SOCKET_ENOTCONN', 107);
define ('SOCKET_ESHUTDOWN', 108);
define ('SOCKET_ETOOMANYREFS', 109);
define ('SOCKET_ETIMEDOUT', 110);
define ('SOCKET_ECONNREFUSED', 111);
define ('SOCKET_EHOSTDOWN', 112);
define ('SOCKET_EHOSTUNREACH', 113);
define ('SOCKET_EALREADY', 114);
define ('SOCKET_EINPROGRESS', 115);
define ('SOCKET_EISNAM', 120);
define ('SOCKET_EREMOTEIO', 121);
define ('SOCKET_EDQUOT', 122);
define ('SOCKET_ENOMEDIUM', 123);
define ('SOCKET_EMEDIUMTYPE', 124);

TCP Multiplexing

RFC 793: To allow for many processes within a single Host to use TCP communication facilities simultaneously, the TCP provides a set of addresses or ports within each host. Concatenated with the network and host addresses from the internet communication layer, this forms a socket. A pair of sockets uniquely identifies each connection. That is, a socket may be simultaneously used in multiple connections.

The binding of ports to processes is handled independently by each Host. However, it proves useful to attach frequently used processes (e.g., a "logger" or timesharing service) to fixed sockets which are made known to the public. These services can then be accessed through the known addresses. Establishing and learning the port addresses of other processes may involve more dynamic mechanisms.

TCP Connections

The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream. The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection. Each connection is uniquely specified by a pair of sockets identifying its two sides.

When two processes wish to communicate, their TCP's must first establish a connection (initialize the status information on each side). When their communication is complete, the connection is terminated or closed to free the resources for other uses.

Since connections must be established between unreliable hosts and over the unreliable internet communication system, a handshake mechanism with clock-based sequence numbers is used to avoid erroneous initialization of connections.

Transfer-Encoding

RFC 2068

19.4.6 Introduction of Transfer-Encoding

   HTTP/1.1 introduces the Transfer-Encoding header field (section
   14.40).  Proxies/gateways MUST remove any transfer coding prior to
   forwarding a message via a MIME-compliant protocol.

   A process for decoding the "chunked" transfer coding (section 3.6)
   can be represented in pseudo-code as:

          length := 0
          read chunk-size, chunk-ext (if any) and CRLF
          while (chunk-size > 0) {
             read chunk-data and CRLF
             append chunk-data to entity-body
             length := length + chunk-size
             read chunk-size and CRLF
          }
          read entity-header
          while (entity-header not empty) {
             append entity-header to existing header fields
             read entity-header
          }
          Content-Length := length
          Remove "chunked" from Transfer-Encoding

Socket-Related Man Pages

DESCRIPTION
This  manual  page  describes the Linux networking socket layer user interface. The BSD compatible sockets are the uniform interface between
the user process and the network protocol stacks in the kernel.  The protocol modules are  grouped  into  protocol  families  like  PF_INET,
PF_IPX, PF_PACKET and socket types like SOCK_STREAM or SOCK_DGRAM.  See socket(2) for more information on families and types.

SOCKET LAYER FUNCTIONS
These  functions  are  used by the user process to send or receive packets and to do other socket operations. For more information see their
respective manual pages.

socket(2) creates a socket, connect(2) connects a socket to a remote socket address, the bind(2) function binds a socket to a  local  socket
address,  listen(2)  tells  the socket that new connections shall be accepted, and accept(2) is used to get a new socket with a new incoming
connection.  socketpair(2) returns two connected anonymous sockets (only implemented for a few local families like PF_UNIX)

send(2), sendto(2), and sendmsg(2) send data over a socket, and recv(2), recvfrom(2), recvmsg(2) receive data from a  socket.   poll(2)  and
select(2)  wait  for  arriving  data  or a readiness to send data.  In addition, the standard I/O operations like write(2), writev(2), send-
file(2), read(2), and readv(2) can be used to read and write data.

getsockname(2) returns the local socket address and getpeername(2) returns the remote socket address.  getsockopt(2) and  setsockopt(2)  are
used to set or get socket layer or protocol options.  ioctl(2) can be used to set or read some other options.

close(2) is used to close a socket.  shutdown(2) closes parts of a full duplex socket connection.

Seeking, or calling pread(2) or pwrite(2) with a non-zero position is not supported on sockets.

It  is possible to do non-blocking IO on sockets by setting the O_NONBLOCK flag on a socket file descriptor using fcntl(2).  Then all opera-
tions that would block will (usually) return with EAGAIN (operation should be retried later); connect(2) will return EINPROGRESS error.  The
user can then wait for various events via poll(2) or select(2).

From the FreeBSD man page for socket(2)

Sockets of type SOCK_STREAM are full-duplex byte streams, similar to
pipes.  A stream socket must be in a connected state before any data may
be sent or received on it.  A connection to another socket is created
with a connect(2) system call.  Once connected, data may be transferred
using read(2) and write(2) calls or some variant of the send(2) and
recv(2) functions.  (Some protocol families, such as the Internet family,
support the notion of an ``implied connect'', which permits data to be
sent piggybacked onto a connect operation by using the sendto(2) system
call.)  When a session has been completed a close(2) may be performed.
Out-of-band data may also be transmitted as described in send(2) and
received as described in recv(2).

The communications protocols used to implement a SOCK_STREAM insure that
data is not lost or duplicated.  If a piece of data for which the peer
protocol has buffer space cannot be successfully transmitted within a
reasonable length of time, then the connection is considered broken and
calls will indicate an error with -1 returns and with ETIMEDOUT as the
specific code in the global variable errno.  The protocols optionally
keep sockets ``warm'' by forcing transmissions roughly every minute in
the absence of other activity.  An error is then indicated if no response
can be elicited on an otherwise idle connection for an extended period
(e.g. 5 minutes).	A SIGPIPE signal is raised if a process sends on a
broken stream; this causes naive processes, which do not handle the sig-
nal, to exit.

Have Fun ;)

Tags

December 17th, 2013

Comments Welcome

  • Mike Schinkel

    GREAT, AWESOME STUFF!

    Unfortunately, your print stylesheet doesn't work on this post, especially not using IE7 but also not using FF2.

    Also, can I suggest you loose the "windoze" references in the future? Your knowledge and skills are too significant that you really shouldn't diminished yourself by self-selecting into the Microsoft-haters faction. The people with the resources to pay you the $175/hour you mention in your "Contact Me" form are usually the type that would view that such hating as immature.

  • AskApache

    @ Mike

    Good suggestion, I changed it to Windows... although I have many reasons for my feelings towards "the empire" that I won't get into. I also fixed the print issue for you, thanks for your help dude!

  • Marcello

    Hi, thanks for your example.
    I've run it and found a little bug, change line 75:

    $port   = (isset($ub['port']) && !empty($ub['port'])) ? $ub['port']:($proto!='')?443:80;
    #to this
    $port   = (isset($ub['port']) && !empty($ub['port'])) ? $ub['port']:(($proto!='')?443:80);

    I've added parenthesis around the second '?:' operator otherwise it will takes precedence on the first and you'll get your port ignored :(

    Ciao,
    -- bm

  • Muhammad

    Hi,
    I works on two sites that seems sited on the same physical server, Can i use fsockopen on one of them to open a socket on the other.
    Sorry for may bad english.
    Thank

  • brian

    The socket_strerror() example (2nd list of error codes) is incorrect. The keys should begin with 0, not 1. Thus, "broken pipe" should be 32, not 33. Assign the values to $s within the body of the loop to fix.

    • AskApache

      Excellent catch brian, thanks.

      I've updated the output and the code to create it... check it out:

      for ( $i=-50, $s=""; ( $i $sn";
      }

  • AskApache

    Fixed, thanks!

  • AskApache

    Good advice, but ain't ever gonna happen. Old school.

  • fred

    Your recycle bin analogy is incorrect. You can get things back from the recycle bin, nothing comes back from /dev/null


Related Articles


My Online Tools
Popular Articles


Hacking and Hackers

The use of "hacker" to mean "security breaker" is a confusion on the part of the mass media. We hackers refuse to recognize that meaning, and continue using the word to mean someone who loves to program, someone who enjoys playful cleverness, or the combination of the two. See my article, On Hacking.
-- Richard M. Stallman









[hide]

It's very simple - you read the protocol and write the code. -Bill Joy

Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. NCSA HTTPd.
UNIX ® is a registered Trademark of The Open Group. POSIX ® is a registered Trademark of The IEEE.

+Askapache | askapache

Site Map | Contact Webmaster | License and Disclaimer | Terms of Service

↑ TOPMain