|
|
XCV. Socket functionsVaroitus | Varoitus!
T�m� laajennus on EKSPERIMENTAALINEN.
T�m�n laajennuksen ominaisuudet, k�ytt�ytyminen ja funktioiden
nimet ja parametrit voivat muuttua varoituksetta seuraavissa
PHP versioissa.
|
The socket extension implements a low-level interface to the socket
communication functions based on the popular BSD sockets, providing the
possibility to act as a socket server as well as a client.
The socket functions described here are part of an extension to
PHP which must be enabled at compile time by giving the --enable-sockets option to
configure.
For a more generic client-side socket interface, see
fsockopen() and
pfsockopen().
When using these functions, it is important to remember that while
many of them have identical names to their C counterparts, they
often have different declarations. Please be sure to read the
descriptions to avoid confusion.
The socket extension was written to provide a useable interface to the
powerful BSD sockets. Care has been taken that the functions work equally
well on Win32 and Unix implementations. Almost all of the sockets
functions may fail under certain conditions and therefore emit an
E_WARNING message describing the error. Sometimes this
doesn't happen to the desire of the developer. For example the function
socket_read() may suddenly emit an
E_WARNING message because the connection broke
unexpectedly. It's common to suppress the warning with the
@-operator and catch the error code within the
application with the socket_last_error() function. You
may call the socket_strerror() function with this error
code to retrieve a string describing the error. See their description for
more information.
Huomaa:
The E_WARNING messages generated by the socket
extension are in english though the retrieved error message will appear
depending on the current locale (LC_MESSAGES):
Warning - socket_bind() unable to bind address [98]: Die Adresse wird bereits verwendet |
That said, those unfamiliar with socket programming can still find a lot
of useful material in the appropriate Unix man pages, and there is a great
deal of tutorial information on socket programming in C on the web, much
of which can be applied, with slight modifications, to socket programming
in PHP. The might be a good start.
Esimerkki 1. Socket example: Simple TCP/IP server
This example shows a simple talkback server. Change the
address and port variables
to suit your setup and execute. You may then connect to the
server with a command similar to: telnet 192.168.1.53
10000 (where the address and port match your
setup). Anything you type will then be output on the server
side, and echoed back to you. To disconnect, enter 'quit'.
#!/usr/local/bin/php -q
<?php
error_reporting (E_ALL);
/* Allow the script to hang around waiting for connections. */
set_time_limit (0);
/* Turn on implicit output flushing so we see what we're getting
* as it comes in. */
ob_implicit_flush ();
$address = '192.168.1.53';
$port = 10000;
if (($sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
echo "socket_create() failed: reason: " . socket_strerror ($sock) . "\n";
}
if (($ret = socket_bind ($sock, $address, $port)) < 0) {
echo "socket_bind() failed: reason: " . socket_strerror ($ret) . "\n";
}
if (($ret = socket_listen ($sock, 5)) < 0) {
echo "socket_listen() failed: reason: " . socket_strerror ($ret) . "\n";
}
do {
if (($msgsock = socket_accept($sock)) < 0) {
echo "socket_accept() failed: reason: " . socket_strerror ($msgsock) . "\n";
break;
}
/* Send instructions. */
$msg = "\nWelcome to the PHP Test Server. \n" .
"To quit, type 'quit'. To shut down the server type 'shutdown'.\n";
socket_write($msgsock, $msg, strlen($msg));
do {
if (FALSE === ($buf = socket_read ($msgsock, 2048))) {
echo "socket_read() failed: reason: " . socket_strerror ($ret) . "\n";
break 2;
}
if (!$buf = trim ($buf)) {
continue;
}
if ($buf == 'quit') {
break;
}
if ($buf == 'shutdown') {
socket_close ($msgsock);
break 2;
}
$talkback = "PHP: You said '$buf'.\n";
socket_write ($msgsock, $talkback, strlen ($talkback));
echo "$buf\n";
} while (true);
socket_close ($msgsock);
} while (true);
socket_close ($sock);
?> |
|
Esimerkki 2. Socket example: Simple TCP/IP client
This example shows a simple, one-shot HTTP client. It simply
connects to a page, submits a HEAD request, echoes the reply,
and exits.
<?php
error_reporting (E_ALL);
echo "<h2>TCP/IP Connection</h2>\n";
/* Get the port for the WWW service. */
$service_port = getservbyname ('www', 'tcp');
/* Get the IP address for the target host. */
$address = gethostbyname ('www.example.com');
/* Create a TCP/IP socket. */
$socket = socket_create (AF_INET, SOCK_STREAM, 0);
if ($socket < 0) {
echo "socket_create() failed: reason: " . socket_strerror ($socket) . "\n";
} else {
echo "OK.\n";
}
echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect ($socket, $address, $service_port);
if ($result < 0) {
echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
} else {
echo "OK.\n";
}
$in = "HEAD / HTTP/1.0\r\n\r\n";
$out = '';
echo "Sending HTTP HEAD request...";
socket_write ($socket, $in, strlen ($in));
echo "OK.\n";
echo "Reading response:\n\n";
while ($out = socket_read ($socket, 2048)) {
echo $out;
}
echo "Closing socket...";
socket_close ($socket);
echo "OK.\n\n";
?> |
|
- Sis�llys
- socket_accept -- Accepts a connection on a socket
- socket_bind -- Binds a name to a socket
- socket_clear_error -- Clears the error on the socket or the last error code
- socket_close -- Closes a socket resource
- socket_connect -- Initiates a connection on a socket
- socket_create -- Create a socket (endpoint for communication)
- socket_create_listen -- Opens a socket on port to accept connections
- socket_create_pair -- Creates a pair of indistinguishable sockets and stores them in fds.
- socket_get_option -- Gets socket options for the socket
- socket_getpeername --
Queries the remote side of the given socket which may either result in host/port
or in a UNIX filesystem path, dependent on its type.
- socket_getsockname --
Queries the local side of the given socket which may either result in host/port
or in a UNIX filesystem path, dependent on its type.
- socket_iovec_add -- Adds a new vector to the scatter/gather array
- socket_iovec_alloc -- ...]) Builds a 'struct iovec' for use with sendmsg, recvmsg, writev, and readv
- socket_iovec_delete -- Deletes a vector from an array of vectors
- socket_iovec_fetch -- Returns the data held in the iovec specified by iovec_id[iovec_position]
- socket_iovec_free -- Frees the iovec specified by iovec_id
- socket_iovec_set -- Sets the data held in iovec_id[iovec_position] to new_val
- socket_last_error -- Returns the last error on the socket
- socket_listen -- Listens for a connection on a socket
- socket_read -- Reads a maximum of length bytes from socket
- socket_readv -- Reads from an fd, using the scatter-gather array defined by iovec_id
- socket_recv -- Receives data from a connected socket
- socket_recvfrom -- Receives data from a socket, connected or not
- socket_recvmsg -- Used to receive messages on a socket, whether connection-oriented or not
- socket_select -- Runs the select() system call on the given arrays of sockets with a timeout specified by tv_sec and tv_usec
- socket_send -- Sends data to a connected socket
- socket_sendmsg -- Sends a message to a socket, regardless of whether it is connection-oriented or not
- socket_sendto -- Sends a message to a socket, whether it is connected or not
- socket_set_nonblock -- Sets nonblocking mode for file descriptor fd
- socket_set_option -- Sets socket options for the socket
- socket_shutdown -- Shuts down a socket for receiving, sending, or both.
- socket_strerror -- Return a string describing a socket error
- socket_write -- Write to a socket
- socket_writev -- Writes to a file descriptor, fd, using the scatter-gather array defined by iovec_id
User Contributed Notes Socket functions |
|
05-Jun-2001 04:49 |
|
After several hours of working with sockets in an attempt to do UDP
broadcasting, I thought a little help was in order for anyone else looking
to do something similar, since it uses a number of those
"undocumented" functions. Here's how I did it:
<?php
// here is a basic opening of the a socket. AF_INET specifies the
internet domain. SOCK_DGRAM
// specifies the Datagram socket type the 0 specifies that I want to use
the default protcol (which in this
// case is UDP)
$sock = socket(AF_INET, SOCK_DGRAM, 0);
// if the file handle assigned to socket is less than 0 then opening the
socket failed
if($sock < 0)
{
echo "socket() failed, error: " . strerror($sock) .
"\n";
}
// here's where I set the socket options, this is essential to allow
broadcasting. An earlier comment (as of
// June 4th, 2001) explains what the parameters are. For my purposes (UDP
broadcasting) I need to set
// the broadcast option at the socket level to true. In C, this done
using SOL_SOCKET as the level param
// (2) and SO_BROADCAST as the type param (3). These may exist in PHP but
I couldn't reference them
// so I used the values that referencing these variables in C returns
(namely 1 and 6 respectively). This
// function is basically just a wrapper to the C function so check out
the C documentation for more info
$opt_ret = setsockopt($sock, 1, 6, TRUE);
// if the return value is less than one, an error occured setting the
options
if($opt_ret < 0)
{
echo "setsockopt() failed, error: " . strerror($opt_ret) .
"\n";
}
// finally I am ready to broad cast something. The sendto function
allows this without any
// connections (essential for broadcasting). So, this function sends the
contents of $broadcast_string to the
// general broadcast address (255.255.255.255) on port 4096. The 0 (param
4) specifies no special
// options, you can read about the options with man sendto
$send_ret = sendto($sock, $broadcast_string, strlen($broadcast_string),
0, '255.255.255.255', 4096);
// if the return value is less than 0, an error has occured
if($send_ret < 0)
{
echo "sendto() failed, error: " . strerror($send_ret) .
" \n"; }
// be sure to close your socket when you're done
close($sock);
|
|
18-Feb-2002 12:27 |
|
Below is a simple forked daemon I wrote in PHP. I haven't seen one yet
anywhere else, so I thought some people might be wondering how to do it.
Execute
with php -q <file>
<?PHP
/*
PHP forked daemon
Standalone PHP binary must be compiled with --enable-sockets and
--enable-pcntl
Dave M. -2002
Online Services USA
*/
function sig_handler($signo) {
switch($signo) {
case SIGTERM:
// handle shutdown tasks
exit;
break;
case SIGHUP:
// handle restart tasks
break;
case SIGUSR1:
print "Caught SIGUSR1...\n";
break;
case SIGCHLD:
while( pcntl_waitpid(-1,$status,WNOHANG)>0 ) {
}
break;
case SIGINT:
exit;
default:
// not implemented yet...
break;
}
}
function interact($sock) {
// Custom code goes here... e.g: socket_read() socket_write()...
}
function become_daemon() {
$child = pcntl_fork();
if($child) {
exit; // kill parent
}
posix_setsid(); // become session leader
chdir("/");
umask(0); // clear umask
return posix_getpid();
}
function open_pid_file($file) {
if(file_exists($file)) {
$fp = fopen($file,"r");
$pid = fgets($fp,1024);
fclose($fp);
if(posix_kill($pid,0)) {
print "Server already running with PID: $pid\n";
exit;
}
print "Removing PID file for defunct server process $pid\n";
if(!unlink($file)) {
print "Cannot unlink PID file $file\n";
exit;
}
}
if($fp = fopen($file,"w")) {
return $fp;
} else {
print "Unable to open PID file $file for writing...\n";
exit;
}
}
function change_identity($uid,$gid) {
global $pid_file;
if(!posix_setgid($gid)) {
print "Unable to setgid to $gid!\n";
unlink($pid_file);
exit;
}
if(!posix_setuid($uid)) {
print "Unable to setuid to $uid!\n";
unlink($pid_file);
exit;
}
}
error_reporting (4);
set_time_limit (0);
ob_implicit_flush ();
$pid_file = '/tmp/php_daemon.pid';
$underpriv_uid = '99'; // uid 99 == user nobody, at least on my system.
$underpriv_gid = '99';
$port = 10000;
$address = 0; // 0 binds to all addresses, may not work on fbsd
$quit = 0;
pcntl_signal(SIGCHLD, "sig_handler");
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT, "sig_handler");
$fh = open_pid_file($pid_file);
if (($sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
print "socket_create() failed: reason: " . socket_strerror
($sock) . "\n";
}
if (($ret = socket_bind ($sock, $address, $port)) < 0) {
print "socket_bind() failed: reason: " . socket_strerror
($ret) . "\n";
}
if (($ret = socket_listen ($sock, 0)) < 0) {
print "socket_listen() failed: reason: " . socket_strerror
($ret) . "\n";
}
change_identity($underpriv_uid,$underpriv_gid);
print "Server ready. Waiting for connections.....\n";
$pid = become_daemon();
fputs($fh,$pid);
fclose($fh);
while(!$quit) {
if (($connection = socket_accept($sock)) < 0) {
next;
}
if( ($child = pcntl_fork()) == -1 ) {
print "Could not fork!!\n";
print "Dying...\n";
$quit++;
}
elseif($child == 0) {
socket_close($sock);
interact($connection);
exit;
}
socket_close($connection);
}
if(posix_getpid() == $pid) {
unlink($pid_file);
}
|
|
daniel[at]lorch.cc
22-Feb-2002 03:32 |
|
"Beej's Guide to Network Programming" is an absolutely excellent
and easy to understand tutorial to socket programming. It was written for
C developers, but as the socket functions in PHP are (almost) analoguous,
this should not be a problem.
|
|
daniel[at]lorch.cc
02-Apr-2002 12:31 |
|
Although this is not the primary use of PHP, writing a server daemon in PHP
is easily feasible.
The most advanced webserver I've seen so far (with an incredible
feature-list) is nanoweb:
<advertizing>
I'm trying to do the same thing, but I'm less advanced than nanoweb. My
primary goal is to create a "framework" on top other developers
should be able to easily create *any* server. Feel free to join the
project :)
</advertizing>
|
|
Pieter
09-Apr-2002 08:03 |
|
On Windows it's also possible to use sockets
Just open your PHP.ini and look for the following part:
;extension=extensions\php_sockets.dll
Unmark it like this
extension=extensions\php_sockets.dll
and there's Sockets to be build in your programs
|
|
23-May-2002 05:54 |
|
Hello,
I use this script to get files from remote location but...:
$fp = fsockopen ($address, 80, $errno, $errstr, 30);
$newfile = fopen($newfile,"w") or DIE ("Error while
creating new file");
if (!$fp) {
echo "$errstr ($errno) \n";
} else {
fputs ($fp, "GET /".$file." HTTP/1.0\n\r
Host: $mysite\n\r\n\r");
while (!feof($fp)) {
$record=fgets ($fp,128);
fputs ($newfile, $record);
echo $record;
}
fclose ($fp);
fclose($newfile);
}
...i have a file with header response, and i dont know how to get
"clear" files...
Any suggest?
|
|
06-Jun-2002 02:24 |
|
Unfortunately the very important function
socket_setopt() for socket options is not yet
documented in this manual!
bool socket_setopt (resource socket, int level, int optname, int )
It is very similar to setsockopt() in C!
|
|
16-Jun-2002 01:08 |
|
Great, that warning about versions. No I use 4.1.2 and can only use the
function socket_clear_error (PHP 4 >= 4.2.0). The rest is 4.1.0. I'm
impressed!
Billy
|
|
|
| |