socket_recv

(PHP 4 >= 4.1.0, PHP 5, PHP 7)

socket_recvBağlı bir soketten veri alır

Açıklama

socket_recv ( resource $soket , string &$tampon , int $uzunluk , int $seçenekler ) : int

socket_recv() işlevi soket ile belirtilen soketten tampon içindeki uzunluk baytı okur. socket_recv() ayrıca, bağlantılı soketlerden veri toplama için de kullanılır. Buna ek olarak işlevin davranışlarında değişiklik yapmak için bir veya daha fazla sayıda seçenek belirtilebilir.

tampon gönderimli aktarılır, dolayısıyla işlevin değiştirgeleri arasında bir değişken olarak yer almalıdır. socket_recv() tarafından socket soketinden okunan veri tampon'a konarak döndürülür.

Değiştirgeler

socket

socket_create() ile oluşturulmuş geçerli bir soket özkaynağı.

tampon

Verinin alınacağı değişken burada belirtilir. Bir hata oluşursa, bağlantı kesilirse veya alınacak bir veri yoksa tampon içeriği olarak NULL atanır.

uzunluk

Okunacak azami bayt sayısını belirler.

seçenekler

Aşağıdaki seçeneklerin bitsel VEYAlanmış bir birleşimi.

Olası seçenekler
MSG_OOB Band dışı veri gönderilir.
MSG_EOR Bir kayıt imi belirtir. Gönderilen veri kaydın tamamlanmasını sağlar.
MSG_EOF Soketin gönderici tarafı kapatılır ve gönderilen verinin sonuna bununla ilgili bir bildirim yerleştirilir. Gönderilen veri aktarımın tamamlanmasını sağlar.
MSG_DONTROUTE Yönlendirme es geçilip doğrudan arabirim kullanılır.

Dönen Değerler

Bir hata oluşmuşsa FALSE yoksa alınan bayt sayısını döndürür. Oluşan hatanın kodu socket_last_error() ile açıklaması ise, elde edilen hata kodu socket_strerror() işlevine aktarılarak alınabilir.

Örnekler

Örnek 1 - socket_recv() örneği

Bu örnek, Örnekler arasında socket_recv() kullanan ilk örneğin yeniden yazılmışıdır.

<?php
error_reporting
(E_ALL);

echo 
"<h2>TCP/IP Bağlantısı</h2>\n";

/* HTTP hizmeti için portu öğrenelim. */
$service_port getservbyname('www''tcp');

/* Hedef konağın IP adresini alalım. */
$address gethostbyname('www.example.com');

/* Bir TCP/IP soketi oluşturalım. */
$socket socket_create(AF_INETSOCK_STREAMSOL_TCP);
if (
$socket === false) {
    echo 
"socket_create() başısız oldu: sebep: " .
    
socket_strerror(socket_last_error()) . "\n";
} else {
    echo 
"OK.\n";
}

echo 
"'$service_port' portundun '$address' adresine bağlanmaya çalışılıyor...";
$result socket_connect($socket$address$service_port);
if (
$result === false) {
    echo 
"socket_connect() başısız oldu:\nSebep: ($result) " .
    
socket_strerror(socket_last_error($socket)) . "\n";
} else {
    echo 
"OK.\n";
}

$in "HEAD / HTTP/1.1\r\n";
$in .= "Host: www.example.com\r\n";
$in .= "Connection: Close\r\n\r\n";
$out '';

echo 
"HTTP HEAD isteğini gönderelim...";
socket_write($socket$instrlen($in));
echo 
"OK.\n";

echo 
"Yanıtı okuyalım:\n\n";
$buf 'Bu bir veri tamponu verisidir.';
if (
false !== ($bytes socket_recv($socket$buf2048MSG_WAITALL))) {
    echo 
"Read $bytes bytes from socket_recv(). Closing socket...";
} else {
    echo 
"socket_recv() failed; reason: " .
    
socket_strerror(socket_last_error($socket)) . "\n";
}
socket_close($socket);

echo 
$buf "\n";
echo 
"OK.\n\n";
?>

Yukarıdaki örnek şuna benzer bir çıktı üretir:

<h2>TCP/IP Bağlantısı</h2>
OK.
'80' portundan '208.77.188.166' adresine bağlanmaya çalışılıyor...OK.
HTTP HEAD isteği gönderiliyor...OK.
Okunan yanıt:

Soket kapatıyor...HTTP/1.1 200 OK
Date: Mon, 14 Sep 2009 08:56:36 GMT
Server: Apache/2.2.3 (Red Hat)
Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT
ETag: "b80f4-1b6-80bfd280"
Accept-Ranges: bytes
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8

OK.

add a note add a note

User Contributed Notes 12 notes

up
26
dgk at tcde dot ru
15 years ago
I've used socket_select and socket_recv with a while loop and found myself in trouble when remote side closed connection. The code below produced infinite loop and socket_select returned immediately (which lead to high cpu time consumption).

<?

socket_set_nonblock($my_socket);
$streams = array($my_socket/*, ... */);

$lastAccess = time();
while (socket_select($streams, $write = NULL, $except = NULL, SLEEP_TIME_SECONDS, SLEEP_TIME_MILLISECONDS) !== FALSE) {
    if (in_array($my_socket, $streams)) {
        while (@socket_recv($my_socket, $data, 8192, 0)) {
            echo $data;
        }
        $lastAccess = time();
    } else {
        if (time()-$lastAccess > LAST_ACCESS_TIMEOUT) {
            break;
        }
    }
    // ...
    $streams = array($my_socket/*, ... */);
}

?>

The solution was simple, but quite hard to find because socket_recv is not documented. socket_recv returns FALSE if there is no data and 0 if the socket is widowed (disconnected by remote side). So I had just to check return value of socket_recv. The problem now sounds stupid, but I've spend some time to find it out.
I hope this will save some of somebody's hair ;)
up
11
m_lajos at hotmail dot com
6 years ago
Workaround for the missing MSG_DONTWAIT flag according to the bug report page:

<?php if(!defined('MSG_DONTWAIT')) define('MSG_DONTWAIT', 0x40); ?>
up
9
ss-130 at yandex dot ru
7 years ago
<?php
$er
= error_reporting(0);
$bytes    = socket_recv($socket,$buffer,1,MSG_WAITALL);
error_reporting($er);

// MEGA BUG HERE
// this statuses are wrong and swapped, closed socket must be with "FALSE"
// but in fact he swap the values:
// http://php.net/manual/en/function.socket-recv.php
//
if($bytes===false){ // no data available, socket not closed
   
echo 'WS_READ_ERR1: '.socket_strerror(socket_last_error($socket)).PHP_EOL;
   
// print when no data available:
    // WS_READ_ERR1: Resource temporarily unavailable
   
continue;
}else if(
$bytes===0){ // socket closed
   
echo 'WS_READ_ERR2: '.socket_strerror(socket_last_error($socket)).PHP_EOL;
   
// print when socket closed:
    // WS_READ_ERR2: Success
   
$process->close();
}

?>
up
2
rathamahata at rathamahata dot net
15 years ago
It looks like that mysterious flags are just the recv(2) flags passed to your OS syscall and nothing more...

ext/sockets/sockets.c:PHP_FUNCTION(socket_recv)
...
        if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) {
                efree(recv_buf);
...

for linux you can type `man 2 recv' and you will see complete description of thouse flags.

Sergey S. Kosrtyliov <rathamahata@rathamahata.net>
http://www.rathamahata.net/
up
1
bastiaan at [no-spam] megabass dot nl
16 years ago
in case you want to empty/unset $buffer, but failing to do so, try using 0 as flag.
PHP_NORMAL_READ and PHP_BINARY_READ respectively hold 1 and 2 as value.
up
1
davide dot renzi at gmail dot com
8 years ago
In PHP version 5.* there is a bug: MSG_DONTWAIT flag is not defined (see https://bugs.php.net/bug.php?id=48326)
up
1
lexkrstn at gmail dot com
1 year ago
It seems like the flags are just passed to the underlying recv() function of your OS, hence there no MSG_DONTWAIT flag on Windows and you should not define it yourself in that case, it just won't work.
up
0
Anonymous
15 years ago
I'm glad that Bastion left the above post about the mysterious int flag. He just helped to fix a problem that I've spent six hours on. Here's my code:

for($ct=1; $ct<=$numrecs; $ct++) {
     $rec = "";
     $nr=socket_recv($fp,$rec,77,0);
     print "Rec # $ct -->";
         print "$rec";
         print "<br>";
      }

The code is pretty simple, it just loops through all my records and prints them out. All records are 77 bytes and all end with a period. The first 36 records print perfectly then at 37 things go bad. The records start to get offset. The last few characters of the 37th record end up printing on the 38th record. The data on the sending side was perfect, so I knew that the problem was with socked_recv.

After reading the above post I tried changing the int flag. Changing the flag to 2 worked:
$nr=socket_recv($fp,$rec,77,2);

Now everything lines up perfectly. I had always left int flag as 0 since it's undocumented.

Martin K.
up
-2
e-vela at bol dot com dot br
3 years ago
Usage example for MSG_PEEK: this function tells if the socket has data available to be read, but preserving it to be read at a future moment.

<?php
// Workaround for the missing define
if(!defined('MSG_DONTWAIT')) define('MSG_DONTWAIT', 0x40);

// Function to check if there is data available in the socket
function SocketHasData($socket) {
   
// Based on the following fact:
    // $result=0 -> disconnected, $result=false -> no data

   
$data = ''; // We need a buffer, but we won't use it

    // MSG_PEEK means to preserve data in the queue, so it can
    // actually be read afterwards
   
$result = socket_recv($socket, $data, 1, MSG_PEEK | MSG_DONTWAIT );

    if (
$result === false) return false; // If no data, returns false
   
return true; // Otherwise returns true
}
?>
up
-1
Anonymous
15 years ago
My last post was incorrect. The int flag set to 2 apparently reset the file position pointer so what I was reading was the first record repeatedly.

My workaroud ended up being the following:

for($ct=1; $ct<=$numrecs; $ct++) {
    $rec = "";
    $nr=socket_recv($fp,$rec,76,0);
       
    //grab the extra bytes.
    $terminator = "";
    while ($terminator != ".") {
        $nr=socket_recv($fp,$terminator,1,0);
    }
   
     $custarray[]=substr($rec,0,76);        
}

Martin K.
up
-2
cottton at i-stats dot net
6 years ago
socket_recv()
returns FALSE if client returned no data
returns 0 (zero) if client disconnected

also (asuming case socket_select() "gave" us a "changed" socket):
if
socket_recv() returned FALSE
and no bytes were received
then
client "crashed" (call it disconnected).

else if
socket_recv() returned 0 (zero)
and no bytes were received
then
client "normaly" disconnected.

Im pretty sure -- 99.99%.
Example:
<?php
function receive($socket)
{
   
// !
    // on all following cases we assume that
    // socket_select() returned the current socket as "changed"
    // !

   
$timeout = 3; // set your timeout

    /* important */
   
$socket_recv_return_values['no_data_received'] = false;
   
$socket_recv_return_values['client_disconnected'] = 0;

   
$start = time();
   
$received_data = null;
   
$received_bytes = null;
   
socket_set_nonblock($socket);
   
socket_clear_error();
    while(
        (
$t_out=((time()-$start) >= $timeout)) === false
       
and ($read=@socket_recv($socket, $buf, 4096, 0)) >= 1
   
){
       
$received_data  = (isset($received_data)) ? $received_data . $buf : $buf;
       
$received_bytes = (isset($received_bytes)) ? $received_bytes + $read : $read;
    }
   
$last_error = socket_last_error($socket);
   
socket_set_block($socket);

    if(
$t_out === true){
        throw new
Exception(
           
'timeout after ' . ((!$received_bytes) ? 0 : $received_bytes) . ' bytes',
           
0 // your eCode here
       
);
    }
    elseif(
$last_error !== false and $last_error !== 0){
        throw new
Exception(
           
socket_strerror($last_error),
           
$last_error
       
);
    }
    else{
        if(
$read === $socket_recv_return_values['no_data_received']){
           
// client returned NO DATA
            // but we were in a loop and could have got some data before:
           
if($received_bytes < 1){
               
// client is connected but sent NO DATA ?
                // no:
                // in this case the client must be "crashed" because -
                // it is not possible to "send no data" (zero bytes)
                // socket_select() now returns this socket as "changed" "forever"
               
throw new Exception(
                   
'client crashed',
                   
0 // your eCode here
               
);
            }else{
               
// client returned DATA
               
return $received_data;
            }
        }
        elseif(
$read === $socket_recv_return_values['client_disconnected']){
           
// client disconnected
           
if($received_bytes < 1){
               
// client disconnected before/without sending any bytes
               
throw new Exception(
                   
'client disconnected',
                   
0 // your eCode here
               
);
            }
            else{
               
// *this value* ^= $socket_recv_return_values['client_disconnected']
                //
                // client disconnected AFTER sending data (we were in a loop!)
                // socket_select() will return this socket "forever" as "changed" and -
                // socket_recv() will return *this value* "forever".
                // we will be "back" again "very soon" to see:
                //  socket_recv() returns *this value* AND no bytes received
                //  which results in disconnect-exception above
               
return $received_data;
            }
        }
    }
}
?>
up
-3
engine at [NO SPAM] illusiononly dot com
15 years ago
To read from socket both on linux and windows OS having  flash as a client I use function bellow. $length is the size of  a chunk, not the max length to read. It will continue reading until EOL char  occures or client disconnects (or in case of error), so it works for bigger packets as well.

     function read($descriptor, $length = 1024) {
            $this->method = "read";
            if(!$client){
                echo("No valid socket descriptor !\n");
                return false;
            }
            $read ='';
        while(($flag=socket_recv($descriptor, $buf, $length,0))>0){
              $asc=ord(substr($buf, -1));
            if ($asc==0) {
                $read.=substr($buf,0,-1);
                break;
            }else{
                $read.=$buf;
            }
        }
           if ($flag<0){
            //error
            return false;
        }elseif ($flag==0){
            //Client disconnected
            return  false;
        }else{
              return $read;
        }

     }
To Top