|
|
XCVI. Socket functionsBevezet�s
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.
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.
Those unfamiliar with socket programming can 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.
Figyelem | Ez a kiterjeszt�s
K�S�RLETI JELLEGGEL M�K�DIK. Ez azt jelenti,
hogy minden itt dokument�lt m�k�d�s, bele�rtve a f�ggv�nyek
nev�t, m�k�d�s�t vagy b�rmi m�s, amit a kiterjeszt�s kapcs�n
le�rtunk megv�ltozhat egy k�s�bbi PHP kiad�sban minden
figyelmeztet�s n�lk�l. Ezt a kiterjeszt�st csak a saj�t
felel�ss�gedre haszn�ld! |
K�vetelm�nyekAz itt le�rt f�ggv�nyek a standard modulban
tal�lhat�ak, ami mindig rendelkez�sre �ll. Telep�t�s
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.
Fut�sidej� be�ll�t�sokEz a kiterjeszt�s semmilyen konfigur�ci�s
be�ll�t�sokat nem defini�l. Er�forr�s t�pusokEz a kiterjeszt�s semmilyen er�forr�s
t�pust nem defini�l. El�re defini�lt �lland�k
Az itt list�zott �lland�kat ez a kiterjeszt�s
defini�lja, �s csak akkor el�rhet�ek, ha az adott
kiterjeszt�s be van ford�tva a PHP-be, vagy
dinamikusan bet�lt�tt. Socket Errors
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.
Megjegyz�s:
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 |
P�ld�k
P�lda 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);
?> |
|
P�lda 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";
?> |
|
- Tartalom
- 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 Socket functions |
|
[email protected]
05-Jun-2001 05: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 01: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 04: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 01: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 09: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 02: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 11: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 04: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)
|
|
|
| |