Php функции работы с сокетами

Функции сокета

After many non-sleep nights I got the most simple multi-client server written in PHP that really works. Ctrl+C and Ctrl+V. use as command line to test it. Enjoy it.

ini_set ( ‘error_reporting’ , E_ALL ^ E_NOTICE );
ini_set ( ‘display_errors’ , 1 );

// Set time limit to indefinite execution
set_time_limit ( 0 );

// Set the ip and port we will listen on
$address = ‘10.203.9.67’ ;
$port = 6901 ;

// Create a TCP Stream socket
$sock = socket_create ( AF_INET , SOCK_STREAM , 0 );

// Bind the socket to an address/port
socket_bind ( $sock , $address , $port ) or die( ‘Could not bind to address’ );

// Start listening for connections
socket_listen ( $sock );

// Non block socket type
socket_set_nonblock ( $sock );

// Loop continuously
while ( true )
<
unset( $read );

if ( count ( $client ))
<
foreach ( $client AS $k => $v )
<
$read [ $j ] = $v ;

if ( $newsock = @ socket_accept ( $sock ))
<
if ( is_resource ( $newsock ))
<
socket_write ( $newsock , » $j >» , 2 ). chr ( 0 );

echo «New client connected $j » ;

if ( count ( $client ))
<
foreach ( $client AS $k => $v )
<
if (@ socket_recv ( $v , $string , 1024 , MSG_DONTWAIT ) === 0 )
<
unset( $client [ $k ]);

// Close the master sockets
socket_close ( $sock );
?>

I’ve been using the ICMP Checksum calculation function written by Khaless [at] bigpond [dot] com. But when having an odd length of data, it failed, so I made my own instead, which adds a 0 if the data length is odd:
function icmpChecksum ( $data )
// Add a 0 to the end of the data, if it’s an «odd length»
if ( strlen ( $data )% 2 )
$data .= «\x00» ;

// Let PHP do all the dirty work
$bit = unpack ( ‘n*’ , $data );
$sum = array_sum ( $bit );

// Stolen from: Khaless [at] bigpond [dot] com
// The code from the original ping program:
// sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
// sum += (sum >> 16); /* add carry */
// which also works fine, but it seems to me that
// Khaless will work on large data.
while ( $sum >> 16 )
$sum = ( $sum >> 16 ) + ( $sum & 0xffff );

At the moment (2007-09), i don’t find this extension in the PECL, but instead in the usual php extension directory. It needs to be included in the php-ini:

Читайте также:  Php read only properties

(or «.so» — whatever for your system).

Wake on Lan , working ok without configurations, and some features

function wake_on_lan ( $mac , $addr = false , $port = 7 ) //Usage
// $addr:
// You will send and broadcast tho this addres.
// Normaly you need to use the 255.255.255.255 adres, so i made it as default. So you don’t need
// to do anything with this.
// Since 255.255.255.255 have permission denied problems you can use addr=false to get all broadcast address from ifconfig command
// addr can be array with broadcast IP values
// $mac:
// You will WAKE-UP this WOL-enabled computer, you need to add the MAC-addres here.
// Mac can be array too
//
//Return
// TRUE: When socked was created succesvolly and the message has been send.
// FALSE: Something went wrong
//
//Example 1
// When the message has been send you will see the message «Done. »
// if ( wake_on_lan(’00:00:00:00:00:00′))
// echo ‘Done. ‘;
// else
// echo ‘Error while sending’;
//
if ( $addr === false ) exec ( «ifconfig | grep Bcast | cut -d \»:\» -f 3 | cut -d \» \» -f 1″ , $addr );
$addr = array_flip ( array_flip ( $addr ));
>
if( is_array ( $addr )) $last_ret = false ;
for ( $i = 0 ; $i < count ( $ret ); $i ++)
if ( $ret [ $i ]!== false )
$last_ret = wake_on_lan ( $mac , $ret [ $i ], $port );
return( $last_ret );
>
if ( is_array ( $mac )) $ret =array();
foreach( $mac as $k => v )
$ret [ $k ]= wake_on_lan ( $v , $addr , $port );
return( $ret );
>
//Check if it’s an real MAC-addres and split it into an array
$mac = strtoupper ( $mac );
if (! preg_match ( «/([A-F0-9][-:])[A-F0-9]/» , $mac , $maccheck ))
return false ;
$addr_byte = preg_split ( «/[-:]/» , $maccheck [ 0 ]);

//Creating hardware adress
$hw_addr = » ;
for ( $a = 0 ; $a < 6 ; $a ++) //Changing mac adres from HEXEDECIMAL to DECIMAL
$hw_addr .= chr ( hexdec ( $addr_byte [ $a ]));

//Create package data
$msg = str_repeat ( chr ( 255 ), 6 );
for ( $a = 1 ; $a $msg .= $hw_addr ;
//Sending data
if ( function_exists ( ‘socket_create’ )) //socket_create exists
$sock = socket_create ( AF_INET , SOCK_DGRAM , SOL_UDP ); //Can create the socket
if ( $sock ) $sock_data = socket_set_option ( $sock , SOL_SOCKET , SO_BROADCAST , 1 ); //Set
if ( $sock_data ) $sock_data = socket_sendto ( $sock , $msg , strlen ( $msg ), 0 , $addr , $port ); //Send data
if ( $sock_data ) socket_close ( $sock ); //Close socket
unset( $sock );
return( true );
>
>
>
@ socket_close ( $sock );
unset( $sock );
>
$sock = fsockopen ( «udp://» . $addr , $port );
if( $sock ) $ret = fwrite ( $sock , $msg );
fclose ( $sock );
>
if( $ret )
return( true );
return( false );
>
?>

Читайте также:  Rtf to txt python

Planning on sending integer values through as socket, I was surprised to find PHP only supports sending strings.
I came to the conclusion the only way to do it would be to create a string that would evaluate to the same byte values as the integer I wanted to send. So (after much messing about) I created a couple of functions: one to create this ‘string’ and one to convert a received value back to an integer.

//Converts an integer to ‘byte array’ (string), default to 4 ‘bytes’ (chars)
function int2string ( $int , $numbytes = 4 )
$str = «» ;
for ( $i = 0 ; $i < $numbytes ; $i ++) $str .= chr ( $int % 256 );
$int = $int / 256 ;
>
return $str ;
>

//Converts a ‘byte array’ (string) to integer
function string2int ( $str )
$numbytes = strlen ( $str );
$int = 0 ;
for ( $i = 0 ; $i < $numbytes ; $i ++) $int += ord ( $str [ $i ]) * pow ( 2 , $i * 8 );
>
return $int ;
>

//Example
echo int2string ( 16705 , 2 ); // 16-bit integer converts to two bytes: 65, 65; which in turn is ‘AA’
echo string2int ( ‘AA’ ); //back the other way
?>

I have searched long and hard for a ping script that does NOT use EXEC() or SYSTEM(). So far, I have found nothing, so I decided to write my own, which was a task to say the least.

First off, I would like to thank Khaless for their checksum function, converting it from C looked like a task in itself.

Here is the class I wrote

class Net_Ping
var $icmp_socket ;
var $request ;
var $request_len ;
var $reply ;
var $errstr ;
var $time ;
var $timer_start_time ;
function Net_Ping ()
$this -> icmp_socket = socket_create ( AF_INET , SOCK_RAW , 1 );
socket_set_block ( $this -> icmp_socket );
>

function ip_checksum ( $data )
for( $i = 0 ; $i < strlen ( $data ); $i += 2 )
if( $data [ $i + 1 ]) $bits = unpack ( ‘n*’ , $data [ $i ]. $data [ $i + 1 ]);
else $bits = unpack ( ‘C*’ , $data [ $i ]);
$sum += $bits [ 1 ];
>

Читайте также:  Ubuntu web server with php

while ( $sum >> 16 ) $sum = ( $sum & 0xffff ) + ( $sum >> 16 );
$checksum = pack ( ‘n1’ ,~ $sum );
return $checksum ;
>

function start_time ()
$this -> timer_start_time = microtime ();
>

function get_time ( $acc = 2 )
// format start time
$start_time = explode ( » » , $this -> timer_start_time );
$start_time = $start_time [ 1 ] + $start_time [ 0 ];
// get and format end time
$end_time = explode ( » » , microtime ());
$end_time = $end_time [ 1 ] + $end_time [ 0 ];
return number_format ( $end_time — $start_time , $acc );
>

function Build_Packet ()
$data = «abcdefghijklmnopqrstuvwabcdefghi» ; // the actual test data
$type = «\x08» ; // 8 echo message; 0 echo reply message
$code = «\x00» ; // always 0 for this program
$chksm = «\x00\x00» ; // generate checksum for icmp request
$id = «\x00\x00» ; // we will have to work with this later
$sqn = «\x00\x00» ; // we will have to work with this later

// now we need to change the checksum to the real checksum
$chksm = $this -> ip_checksum ( $type . $code . $chksm . $id . $sqn . $data );

// now lets build the actual icmp packet
$this -> request = $type . $code . $chksm . $id . $sqn . $data ;
$this -> request_len = strlen ( $this -> request );
>

function Ping ( $dst_addr , $timeout = 5 , $percision = 3 )
// lets catch dumb people
if ((int) $timeout if ((int) $percision

// set the timeout
socket_set_option ( $this -> icmp_socket ,
SOL_SOCKET , // socket level
SO_RCVTIMEO , // timeout option
array(
«sec» => $timeout , // Timeout in seconds
«usec» => 0 // I assume timeout in microseconds
)
);

if ( $dst_addr )
if (@ socket_connect ( $this -> icmp_socket , $dst_addr , NULL ))

> else $this -> errstr = «Cannot connect to $dst_addr » ;
return FALSE ;
>
$this -> Build_Packet ();
$this -> start_time ();
socket_write ( $this -> icmp_socket , $this -> request , $this -> request_len );
if (@ socket_recv ( $this -> icmp_socket , & $this -> reply , 256 , 0 ))
$this -> time = $this -> get_time ( $percision );
return $this -> time ;
> else $this -> errstr = «Timed out» ;
return FALSE ;
>
> else $this -> errstr = «Destination address not specified» ;
return FALSE ;
>
>
>

$ping = new Net_Ping ;
$ping -> ping ( «www.google.ca» );

if ( $ping -> time )
echo «Time: » . $ping -> time ;
else
echo $ping -> errstr ;

?>

Hope this saves some troubles.

Источник

Оцените статью