|
|
XCVI. SocketsAvertissement | Ce module est EXPERIMENTAL. Cela signifie que le comportement de ces fonctions, leurs noms et concr�tement, TOUT ce qui est document� ici peut changer dans un futur proche, SANS PREAVIS! Soyez-en conscient, et utiliser ce module � vos risques et p�rils. |
L'extension socket impl�mente une interface bas niveau avec les
fonctions de communication par socket. Cela permet de mettre en place
un serveur aussi bien qu'un client.
Les fonctions socket d�crites ici sont rassembl�es dans une extension
PHP. Pour �tre activ�es, il faut utiliser l'option de compilation
--enable-sockets au script
configure.
Pour une interface client plus g�n�rique, reportez vous �
fsockopen() et pfsockopen().
Lorsque vous utiliserez les fonctions de sockets qui sont d�crites ici,
gardez bien � l'esprit que m�me si elles ont souvent des noms identiques
aux fonctions C, elles ont souvent des prototypes diff�rents. Lisez attentivement
la documentation pour �viter les confusions.
Cela dit, ceux qui n'ont pas l'habitude de la programmation avec les sockets
pourront trouver beaucoup de documentation pertinente dans les pages de
manuel Unix, et de nombreux tutorial de programmation C sur le web, dont la
plus part peuvent �tre repris apr�s de l�g�re
modifications, en PHP.
Exemple 1. Exemple de programmation Socket : serveur TCP/IP
Cet exemple est un serveur perroquete : tout ce que vous lui envoyez
vous est retourn�. Changez les variables
address et port pour les adapter �
votre configuration, et lancez le script. Vous pouvez vous connecter
au serveur avec une commande telle que telnet 192.168.1.53 10000
(avec l'adresse et le port qui sont ceux de votre configuration).
Pour vous d�connecter, tapez 'quit'.
<?php
error_reporting(E_ALL);
/* On autorise le script � attendre les connexions ind�finiment. */
set_time_limit(0);
/* Modifiez ces valeurs pour qu'elles soient celles de votre configuration */
$address = '192.168.1.53';
$port = 10000;
if (($sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
echo "socket() a �chou� : raison : " . strerror($sock) . "\n";
}
if (($ret = bind($sock, $address, $port)) < 0) {
echo "bind() a �chou� : raison: " . strerror($ret) . "\n";
}
if (($ret = listen($sock, 5)) < 0) {
echo "listen() a �chou� : raison: " . strerror($ret) . "\n";
}
do {
if (($msgsock = accept_connect($sock)) < 0) {
echo "accept_connect() a �chou� : raison : " . strerror($msgsock) . "\n";
break;
}
do {
$buf = '';
$ret = read($msgsock, $buf, 2048);
if ($ret < 0) {
echo "read() a �chou� : raison : " . strerror($ret) . "\n";
break 2;
}
if ($ret == 0) {
break 2;
}
$buf = trim($buf);
if ($buf == 'quit') {
close($msgsock);
break 2;
}
$talkback = "PHP: Vous avez dit '$buf'.\n";
write($msgsock, $talkback, strlen($talkback));
echo "$buf\n";
} while (TRUE);
close($msgsock);
} while (TRUE);
close($sock);
?> |
|
Exemple 2. Exemple avec les sockets : Client TCP/IP
Cet exemple est un client HTTP basique. Il se connecte � une page
envoi les ent�tes (requ�te HEAD), affiche le retour, et quitte.
<?php
error_reporting(E_ALL);
echo "<h2>TCP/IP Connection</h2>\n";
/* Demande le port du service WWW. */
$service_port = getservbyname('www', 'tcp');
/* Demande l'IP du serveur de destination. */
$address = gethostbyname('www.php.net');
/* Cr�e la connexion TCP/IP. */
$socket = socket(AF_INET, SOCK_STREAM, 0);
if ($socket < 0) {
echo "socket() a �chou� : raison : " . strerror($socket) . "\n";
} else {
"socket() r�ussi: " . strerror($socket) . "\n";
}
echo "Connexion � '$address' on port '$service_port'...";
$result = connect($socket, $address, $service_port);
if ($result < 0) {
echo "connect() a �chou� : raison : : ($result) " . strerror($result) . "\n";
} else {
echo "OK.\n";
}
$in = "HEAD / HTTP/1.0\r\n\r\n";
$out = '';
echo "Envoi des ent�tes HTTP HEAD...";
write($socket, $in, strlen($in));
echo "OK.\n";
echo "Lecture de la r�ponse :\n\n";
while (read($socket, $out, 2048)) {
echo $out;
}
echo "Fermeture de la socket...";
close($socket);
echo "OK.\n\n";
?> |
|
- Table des mati�res
- 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_listen -- Opens a socket on port to accept connections
- socket_create_pair -- Creates a pair of indistinguishable sockets and stores them in fds.
- socket_create -- Create a socket (endpoint for communication)
- 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 a 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 Sockets |
|
[email protected]
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);
|
|
[email protected]
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
|
|
[email protected]
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
|
|
[email protected]
08-Jul-2002 10:03 |
|
To Ramar: All you have to do is to use fopen() function.
Here is an
example of using POST method: $host = "www.php.net"; $data
= "lang=en_US&pattern=sockets&show=quickref";
$fp
= fsockopen($host,80);
fputs($fp, "POST /search.php
HTTP/1.1\n"); fputs($fp, "Host: $host\n"); fputs($fp,
"Content-type:
application/x-www-form-urlencoded\n"); fputs($fp,
"Content-length: " . strlen($data) .
"\n"); fputs($fp, "User-Agent:
MSIE\n"); fputs($fp, "Connection:
close\n\n"); fputs($fp, $data);
while (!feof($fp)) $buf
.= fgets($fp,128); fclose($fp);
echo $buf;
|
|
saryon at unfix dot org
09-Jul-2002 03:42 |
|
I found this EXTREMELY useful link on the zend php mailing
list:
It's
about being able to use multiple connections in a php socket server,
WITHOUT having to use those threads everyone seems to be so very
fond of. works very well :) (ps: i didn't make it, so....don't say
thanks to me ;), thank him)
|
|
|
| |