Socket recv socket error

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

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

socket_recvReceives data from a connected socket

Description

socket_recv(
    Socket $socket,
    ?string &$data,
    int $length,
    int $flags
): int|false

data is passed by reference, so it must be
specified as a variable in the argument list. Data read from
socket by socket_recv()
will be returned in data.

Parameters

socket

The socket must be a Socket instance previously
created by socket_create().

data

The data received will be fetched to the variable specified with
data. If an error occurs, if the
connection is reset, or if no data is
available, data will be set to null.

length

Up to length bytes will be fetched from remote host.

flags

The value of flags can be any combination of
the following flags, joined with the binary OR (|)
operator.

Possible values for flags

Flag Description
MSG_OOB Process out-of-band data.
MSG_PEEK Receive data from the beginning of the receive queue without
removing it from the queue.
MSG_WAITALL Block until at least length are received.
However, if a signal is caught or the remote host disconnects, the
function may return less data.
MSG_DONTWAIT With this flag set, the function returns even if it would normally
have blocked.

Return Values

socket_recv() returns the number of bytes received,
or false if there was an error. The actual error code can be retrieved by
calling socket_last_error(). This error code may be
passed to socket_strerror() to get a textual explanation
of the error.

Changelog

Version Description
8.0.0 socket is a Socket instance now;
previously, it was a resource.

Examples

Example #1 socket_recv() example

This example is a simple rewrite of the first example from
Examples to
use socket_recv().


<?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, SOL_TCP);
if (
$socket === false) {
echo
"socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "n";
} else {
echo
"OK.n";
}

echo

"Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if (
$result === false) {
echo
"socket_connect() failed.nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "n";
} else {
echo
"OK.n";
}
$in = "HEAD / HTTP/1.1rn";
$in .= "Host: www.example.comrn";
$in .= "Connection: Closernrn";
$out = '';

echo

"Sending HTTP HEAD request...";
socket_write($socket, $in, strlen($in));
echo
"OK.n";

echo

"Reading response:nn";
$buf = 'This is my buffer.';
if (
false !== ($bytes = socket_recv($socket, $buf, 2048, MSG_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.nn";
?>

The above example will produce something like:

<h2>TCP/IP Connection</h2>
OK.
Attempting to connect to '208.77.188.166' on port '80'...OK.
Sending HTTP HEAD request...OK.
Reading response:

Read 123 bytes from socket_recv(). Closing socket...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.

dgk at tcde dot ru

18 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 ;)


ss-130 at yandex dot ru

9 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();
}
?>

m_lajos at hotmail dot com

8 years ago


Workaround for the missing MSG_DONTWAIT flag according to the bug report page:

<?php if(!defined('MSG_DONTWAIT')) define('MSG_DONTWAIT', 0x40); ?>


rathamahata at rathamahata dot net

17 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/


bastiaan at [no-spam] megabass dot nl

18 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.

lexkrstn at gmail dot com

4 years 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.

Anonymous

1 year ago


<?phpnamespace Safe;

use

SafeExceptionsSocketsException;/**
* After the socket socket has been created
* using socket_create, bound to a name with
* socket_bind, and told to listen for connections
* with socket_listen, this function will accept
* incoming connections on that socket. Once a successful connection
* is made, a new socket resource is returned, which may be used
* for communication. If there are multiple connections queued on
* the socket, the first will be used. If there are no pending
* connections, socket_accept will block until
* a connection becomes present. If socket
* has been made non-blocking using
* socket_set_blocking or
* socket_set_nonblock, FALSE will be returned.
*
* The socket resource returned by
* socket_accept may not be used to accept new
* connections. The original listening socket
* socket, however, remains open and may be
* reused.
*
* @param resource $socket A valid socket resource created with socket_create.
* @return resource Returns a new socket resource on success. The actual
* error code can be retrieved by calling
* socket_last_error. This error code may be passed to
* socket_strerror to get a textual explanation of the
* error.
* @throws SocketsException
*
*/
function socket_accept($socket)
{
   
error_clear_last();
   
$result = socket_accept($socket);
    if (
$result === false) {
        throw
SocketsException::createFromPhpError();
    }
    return
$result;
}
/**
* Create a Socket resource, and bind it to the provided AddrInfo resource.  The return
* value of this function may be used with socket_listen.
*
* @param resource $addr Resource created from socket_addrinfo_lookup.
* @return resource Returns a Socket resource on success.
* @throws SocketsException
*
*/
function socket_addrinfo_bind($addr)
{
   
error_clear_last();
   
$result = socket_addrinfo_bind($addr);
    if (
$result === null) {
        throw
SocketsException::createFromPhpError();
    }
    return
$result;
}


Anonymous

17 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.


Anonymous

17 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.


engine at [NO SPAM] illusiononly dot com

18 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;
        }

     }


cottton at i-stats dot net

8 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;
            }
        }
    }
}
?>


e-vela at bol dot com dot br

5 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
}
?>


Содержание

  1. socket_recv — Получает данные из подсоединённого сокета
  2. Описание
  3. Список параметров
  4. Возвращаемые значения
  5. Примеры
  6. Соединение TCP/IP
  7. recv function (winsock.h)
  8. Syntax
  9. Parameters
  10. Return value
  11. Remarks
  12. Example Code
  13. Example Code
  14. Функция recv (winsock.h)
  15. Синтаксис
  16. Параметры
  17. Возвращаемое значение
  18. Комментарии
  19. Пример кода
  20. Пример кода

socket_recv — Получает данные из подсоединённого сокета

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

socket_recv — Получает данные из подсоединённого сокета

Описание

Функция socket_recv() получает len байт данных в буфер buf из сокета socket . функция socket_recv() может быть использована для получения данных из подсоединённых сокетов. Дополнительно к этому, один или более флагов могут быть указаны для изменения поведения функции.

Параметр buf передаётся по ссылке, так что он должен быть указан в виде переменной в списке аргументов. Данные, прочитанные из сокета socket функцией socket_recv() , будут возвращены в параметре buf .

Список параметров

Параметр socket должен быть ресурсом сокета, предварительно созданным при помощи функции socket_create().

Полученные данные будут переданы в переменную, указанную в параметре buf . Если происходит ошибка, если соединение сброшено, или если данные недоступны, параметр buf будет установлен в NULL .

До len байт будет получено с удалённого хоста.

Значение параметра flags может быть любой комбинацией следующих флагов, соединённых при помощи двоичного оператора OR (|).

Possible values for flags

Флаг Описание
MSG_OOB Обрабатывать внеполосные (out-of-band) данные.
MSG_PEEK Получать данные с начала очереди получения без удаления их из очереди.
MSG_WAITALL Функция будет блокировать выполнение скрипта до тех пор, пока как минимум len байт не будет получено. Однако, в том случае, если получен сигнал или удалённый хост отсоединился, функция может вернуть меньше данных.
MSG_DONTWAIT Если этот флаг установлен, то функция вернётся даже в том случае, если бы она обычно блокировала исполнение скрипта.

Возвращаемые значения

socket_recv() возвращает количество полученных байтов, или FALSE в случае ошибки. Фактический код ошибки может быть получен при помощи функции socket_last_error() . Этот код ошибки может быть передан функции socket_strerror() для получения текстового описания ошибки.

Примеры

Пример #1 Пример использования socket_recv()

Этот пример — просто вариант первого примера из статьи Примеры с использованием socket_recv() .

Соединение TCP/IP

/* Получить порт сервиса WWW. */
$service_port = getservbyname ( ‘www’ , ‘tcp’ );

/* Получить IP-адрес целевого хоста. */
$address = gethostbyname ( ‘www.example.com’ );

/* Создать сокет TCP/IP. */
$socket = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP );
if ( $socket === false ) <
echo «Не удалось выполнить функцию socket_create(): причина: » . socket_strerror ( socket_last_error ()) . «n» ;
> else <
echo «OK.n» ;
>

echo «Попытка соединиться с хостом ‘ $address ‘ по порту ‘ $service_port ‘. » ;
$result = socket_connect ( $socket , $address , $service_port );
if ( $result === false ) <
echo «Не получилось выполнить функцию socket_connect().nПричина: ( $result ) » . socket_strerror ( socket_last_error ( $socket )) . «n» ;
> else <
echo «OK.n» ;
>

$in = «HEAD / HTTP/1.1rn» ;
$in .= «Host: www.example.comrn» ;
$in .= «Connection: Closernrn» ;
$out = » ;

echo «Отправка запроса HTTP HEAD. » ;
socket_write ( $socket , $in , strlen ( $in ));
echo «OK.n» ;

echo «Получение ответа:nn» ;
$buf = ‘Это мой буфер.’ ;
if ( false !== ( $bytes = socket_recv ( $socket , $buf , 2048 , MSG_WAITALL ))) <
echo «Прочитано $bytes байта из функции socket_recv(). Закрываем сокет. » ;
> else <
echo «Не получилось выполнить socket_recv(); причина: » . socket_strerror ( socket_last_error ( $socket )) . «n» ;
>
socket_close ( $socket );

Пример выше выведет что-то вроде следующего:

Источник

recv function (winsock.h)

The recv function receives data from a connected socket or a bound connectionless socket.

Syntax

Parameters

The descriptor that identifies a connected socket.

A pointer to the buffer to receive the incoming data.

The length, in bytes, of the buffer pointed to by the buf parameter.

A set of flags that influences the behavior of this function. See remarks below. See the Remarks section for details on the possible value for this parameter.

Return value

If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain this data received. If the connection has been gracefully closed, the return value is zero.

Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

Error code Meaning
WSANOTINITIALISED A successful WSAStartup call must occur before using this function.
WSAENETDOWN The network subsystem has failed.
WSAEFAULT The buf parameter is not completely contained in a valid part of the user address space.
WSAENOTCONN The socket is not connected.
WSAEINTR The (blocking) call was canceled through WSACancelBlockingCall.
WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.
WSAENETRESET For a connection-oriented socket, this error indicates that the connection has been broken due to keep-alive activity that detected a failure while the operation was in progress. For a datagram socket, this error indicates that the time to live has expired.
WSAENOTSOCK The descriptor is not a socket.
WSAEOPNOTSUPP MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations.
WSAESHUTDOWN The socket has been shut down; it is not possible to receive on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH.
WSAEWOULDBLOCK The socket is marked as nonblocking and the receive operation would block.
WSAEMSGSIZE The message was too large to fit into the specified buffer and was truncated.
WSAEINVAL The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled or (for byte stream sockets only) len was zero or negative.
WSAECONNABORTED The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no longer usable.
WSAETIMEDOUT The connection has been dropped because of a network failure or because the peer system failed to respond.
WSAECONNRESET The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket as it is no longer usable. On a UDP-datagram socket, this error would indicate that a previous send operation resulted in an ICMP «Port Unreachable» message.

The recv function is used to read incoming data on connection-oriented sockets, or connectionless sockets. When using a connection-oriented protocol, the sockets must be connected before calling recv. When using a connectionless protocol, the sockets must be bound before calling recv.

The local address of the socket must be known. For server applications, use an explicit bind function or an implicit accept or WSAAccept function. Explicit binding is discouraged for client applications. For client applications, the socket can become bound implicitly to a local address using connect, WSAConnect, sendto, WSASendTo, or WSAJoinLeaf.

For connected or connectionless sockets, the recv function restricts the addresses from which received messages are accepted. The function only returns messages from the remote address specified in the connection. Messages from other addresses are (silently) discarded.

For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data as is currently available—up to the size of the buffer specified. If the socket has been configured for in-line reception of OOB data (socket option SO_OOBINLINE) and OOB data is yet unread, only OOB data will be returned. The application can use the ioctlsocket or WSAIoctlSIOCATMARK command to determine whether any more OOB data remains to be read.

For connectionless sockets (type SOCK_DGRAM or other message-oriented sockets), data is extracted from the first enqueued datagram (message) from the destination address specified by the connect function.

If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recv generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost; for reliable protocols, the data is retained by the service provider until it is successfully read by calling recv with a large enough buffer.

If no incoming data is available at the socket, the recv call blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking. In this case, a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select, WSAAsyncSelect, or WSAEventSelect functions can be used to determine when more data arrives.

If the socket is connection oriented and the remote side has shut down the connection gracefully, and all data has been received, a recv will complete immediately with zero bytes received. If the connection has been reset, a recv will fail with the error WSAECONNRESET.

The flags parameter can be used to influence the behavior of the function invocation beyond the options specified for the associated socket. The semantics of this function are determined by the socket options and the flags parameter. The possible value of flags parameter is constructed by using the bitwise OR operator with any of the following values.

Value Meaning
MSG_PEEK Peeks at the incoming data. The data is copied into the buffer, but is not removed from the input queue.
MSG_OOB Processes Out Of Band (OOB) data.
MSG_WAITALL The receive request will complete only when one of the following events occurs:

  • The buffer supplied by the caller is completely full.
  • The connection has been closed.
  • The request has been canceled or an error occurred.

Note that if the underlying transport does not support MSG_WAITALL, or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP. Also, if MSG_WAITALL is specified along with MSG_OOB, MSG_PEEK, or MSG_PARTIAL, then this call will fail with WSAEOPNOTSUPP. This flag is not supported on datagram sockets or message-oriented sockets.

В

Example Code

Example Code

WindowsВ PhoneВ 8: This function is supported for Windows Phone Store apps on WindowsВ PhoneВ 8 and later.

WindowsВ 8.1 and Windows ServerВ 2012В R2: This function is supported for Windows Store apps on WindowsВ 8.1, Windows ServerВ 2012В R2, and later.

Источник

Функция recv (winsock.h)

Функция recv получает данные из подключенного сокета или связанного сокета без подключения.

Синтаксис

Параметры

Дескриптор, идентифицирующий подключенный сокет.

Указатель на буфер для получения входящих данных.

Длина буфера в байтах, на который указывает параметр buf .

Набор флагов, влияющих на поведение этой функции. См. примечания ниже. Дополнительные сведения о возможном значении этого параметра см. в разделе «Примечания».

Возвращаемое значение

Если ошибка не возникает, функция recv возвращает количество полученных байтов, а буфер, на который указывает параметр buf , будет содержать полученные данные. Если подключение было корректно закрыто, возвращаемое значение равно нулю.

В противном случае возвращается значение SOCKET_ERROR, и можно получить определенный код ошибки путем вызова WSAGetLastError.

Код ошибки Значение
WSANOTINITIALISED Перед использованием этой функции необходимо выполнить успешный вызов WSAStartup .
WSAENETDOWN Сбой сетевой подсистемы.
WSAEFAULT Параметр buf не полностью содержится в допустимой части адресного пространства пользователя.
WSAENOTCONN Сокет не подключен.
WSAEINTR Вызов (блокировка) был отменен через WSACancelBlockingCall.
WSAEINPROGRESS Выполняется блокировка вызова сокетов Windows 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.
WSAENETRESET Для сокета, ориентированного на подключение, эта ошибка указывает на то, что подключение было нарушено из-за активности активности, которое обнаружило сбой во время выполнения операции. Для сокета датаграмм эта ошибка указывает на то, что срок жизни истек.
WSAENOTSOCK Дескриптор не является сокетом.
WSAEOPNOTSUPP MSG_OOB указан, но сокет не является потоковым стилем, например типом SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, или сокет является однонаправленным и поддерживает только операции отправки.
WSAESHUTDOWN Сокет был выключен; невозможно получить в сокете после вызова завершения работыс настройкой SD_RECEIVE или SD_BOTH.
WSAEWOULDBLOCK Сокет помечается как неблокировка и операция получения блокируется.
WSAEMSGSIZE Сообщение усечено, так как оно слишком велико для помещения в указанный буфер.
WSAEINVAL Сокет не был привязан к привязке или был указан неизвестный флаг, или MSG_OOB был указан для сокета с включенным SO_OOBINLINE или (только для сокетов потока байтов ) был нулевым или отрицательным.
WSAECONNABORTED Виртуальное подключение разорвано из-за тайм-аута или иного сбоя. Приложение должно закрыть сокет, поскольку он больше не может использоваться.
WSAETIMEDOUT Соединение было разорвано из-за сбоя в сети или отсутствия ответа от одноранговой системы.
WSAECONNRESET Виртуальное подключение было сброшено удаленной стороной путем прерывания. Приложение должно закрыть сокет, поскольку он больше не может использоваться. В сокете UDP-datagram эта ошибка указывает, что предыдущая операция отправки привела к сообщению ICMP «Недоступен порт».

Комментарии

Функция recv используется для чтения входящих данных в сокетах, ориентированных на подключение, или для сокетов без подключения. При использовании протокола, ориентированного на подключение, сокеты должны быть подключены перед вызовом recv. При использовании протокола без подключения сокеты должны быть привязаны перед вызовом recv.

Локальный адрес сокета должен быть известен. Для серверных приложений используйте явную функцию привязки или неявную функцию accept или WSAAccept . Явная привязка не рекомендуется для клиентских приложений. Для клиентских приложений сокет может быть привязан неявно к локальному адресу с помощью подключения, WSAConnect, sendto, WSASendTo или WSAJoinLeaf.

Для подключенных или несоединяемых сокетов функция recv ограничивает адреса, от которых принимаются полученные сообщения. Функция возвращает сообщения только из удаленного адреса, указанного в соединении. Сообщения с других адресов (автоматически) удаляются.

Для сокетов, ориентированных на подключение (например, тип SOCK_STREAM), вызов recv вернет столько данных, сколько доступно в данный момент, вплоть до указанного размера буфера. Если сокет настроен для встроенного приема данных OOB (параметр сокета SO_OOBINLINE) и данные OOB еще нечитаны, будут возвращены только данные OOB. Приложение может использовать команду ioctlsocket или WSAIoctlSIOCATMARK, чтобы определить, остается ли считывать все больше данных OOB.

Для сокетов без подключения (тип SOCK_DGRAM или другие сокеты, ориентированные на сообщения), данные извлекаются из первой диаграммы данных в очереди (сообщения) из адреса назначения, указанного функцией connect .

Если датаграмма или сообщение больше указанного буфера, буфер заполняется первой частью датаграммы и выпрямляет ошибку WSAEMSGSIZE. Для ненадежных протоколов (например, UDP) лишние данные теряются; для надежных протоколов данные сохраняются поставщиком услуг до тех пор, пока не будет успешно прочитано путем вызова recv с достаточно большим буфером.

Если входящие данные не доступны в сокете, прямоугольник вызывает блоки и ожидает поступления данных в соответствии с правилами блокировки, определенными для WSARecv с флагом MSG_PARTIAL не задан, если сокет не блокируется. В этом случае возвращается значение SOCKET_ERROR с кодом ошибки, установленным для WSAEWOULDBLOCK. Функции select, WSAsyncSelect или WSAEventSelect можно использовать для определения времени поступления дополнительных данных.

Если сокет ориентирован на подключение, а удаленная сторона корректно завершит подключение и все данные были получены, выпрямка завершится немедленно с нулевым числом байтов. Если подключение было сброшено, восстановление завершится ошибкой WSAECONNRESET.

Параметр флагов можно использовать для влияния на поведение вызова функции за пределами параметров, указанных для связанного сокета. Семантика этой функции определяется параметрами сокета и параметром флагов . Возможное значение параметра flags создается с помощью побитового оператора OR со следующими значениями.

Значение Значение
MSG_PEEK Просматривает входящие данные. Данные копируются в буфер, но не удаляются из входной очереди.
MSG_OOB Обрабатывает данные вне диапазона (OOB).
MSG_WAITALL Запрос на получение завершится только в том случае, если происходит одно из следующих событий:

  • Буфер, предоставленный вызывающим объектом, полностью заполнен.
  • Соединение было закрыто.
  • Запрос был отменен или произошла ошибка.

Обратите внимание, что если базовый транспорт не поддерживает MSG_WAITALL или если сокет находится в режиме без блокировки, этот вызов завершится ошибкой с WSAEOPNOTSUPP. Кроме того, если MSG_WAITALL указан вместе с MSG_OOB, MSG_PEEK или MSG_PARTIAL, этот вызов завершится ошибкой с WSAEOPNOTSUPP. Этот флаг не поддерживается для сокетов датаграммы или сокетов, ориентированных на сообщения.

Пример кода

Пример кода

Windows Phone 8. Эта функция поддерживается для приложений Магазина Windows Phone в Windows Phone 8 и более поздних версий.

Windows 8.1 и Windows Server 2012 R2: эта функция поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версий.

Источник

In the case of a non blocking socket that has no data available, recv will throw the socket.error exception and the value of the exception will have the errno of either EAGAIN or EWOULDBLOCK. Example:

import sys
import socket
import fcntl, os
import errno
from time import sleep

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
fcntl.fcntl(s, fcntl.F_SETFL, os.O_NONBLOCK)

while True:
    try:
        msg = s.recv(4096)
    except socket.error, e:
        err = e.args[0]
        if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
            sleep(1)
            print 'No data available'
            continue
        else:
            # a "real" error occurred
            print e
            sys.exit(1)
    else:
        # got a message, do something :)

The situation is a little different in the case where you’ve enabled non-blocking behavior via a time out with socket.settimeout(n) or socket.setblocking(False). In this case a socket.error is stil raised, but in the case of a time out, the accompanying value of the exception is always a string set to ‘timed out’. So, to handle this case you can do:

import sys
import socket
from time import sleep

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
s.settimeout(2)

while True:
    try:
        msg = s.recv(4096)
    except socket.timeout, e:
        err = e.args[0]
        # this next if/else is a bit redundant, but illustrates how the
        # timeout exception is setup
        if err == 'timed out':
            sleep(1)
            print 'recv timed out, retry later'
            continue
        else:
            print e
            sys.exit(1)
    except socket.error, e:
        # Something else happened, handle error, exit, etc.
        print e
        sys.exit(1)
    else:
        if len(msg) == 0:
            print 'orderly shutdown on server end'
            sys.exit(0)
        else:
            # got a message do something :)

As indicated in the comments, this is also a more portable solution since it doesn’t depend on OS specific functionality to put the socket into non-blockng mode.

See recv(2) and python socket for more details.

функция recv

int recv( SOCKET s, char FAR *buf, int len, int flags);

Описание параметра

  1. Первый параметр указывает дескриптор получающего сокета;
  2. Второй параметр указывает буфер, который используется для хранения данных, полученных функцией recv;
  3. Третий параметр указывает длину буфера;
  4. Четвертый параметр обычно устанавливается на ноль.

Процесс выполнения функции recv синхронного сокета

Когда приложение вызывает функцию recv:

  1. Сначала recv ожидает передачи данных в буфере отправки SOCKET по протоколу.доставитьПри отправке данных в сПроизошла ошибка сетиЗатем функция recv возвращаетSOCKET_ERROR
  2. Если сОтправить буфервНет данныхилиДанные были успешно отправлены по протоколуПосле recvСначала проверьте приемный буфер сокета s
  3. Если сПриемный буфервНет данныхилиПротокол получения данныхТогда recv былПодождитеПока протокол не получил данные;
  4. Когда протокол завершил получение данных, функция recvПриемный буферДанные вскопировать в буферДюйм (Обратите внимание, что данные, полученные протоколом, могут быть больше, чем длина буфера, поэтому в этом случае функцию recv необходимо вызывать несколько раз, чтобы скопировать данные в приемный буфер функции s. RecvПросто скопируйте данныеФактический прием данных осуществляется протоколом.) Функция recv возвращает количество байтов, которые она фактически скопировала. Если ошибки recv при копировании, то он возвращаетSOCKET_ERROR
  5. Если функция recv находится вОтказ сети при ожидании протокола для получения данныхВверх, то этоВозвращает 0.

Сокет по умолчанию является блокирующим. Нет никакого различия между блокирующими и неблокирующими возвращаемыми значениями recv, оба<0 ошибка = 0 соединение закрыто> 0 получен размер данных.

Возвращаемое значение

  1. После успешного выполнения возвращается количество полученных байтов.
  2. Возвращает 0, если другой конец закрыт.
  3. -1 при ошибке, errno устанавливается в одно из следующих значений:
  • EAGAIN: Сокет был помечен как неблокирующий, и операция приема заблокирована или время ожидания приема истекло
  • EBADF: Sock не является допустимым дескриптором
  • ECONNREFUSE: Удаленный хост блокирует сетевое соединение
  • EFAULT: Ошибка доступа к памяти
  • EINTR: Операция была прервана сигналом
  • EINVAL: Неверный параметр
  • ENOMEM: Недостаточно памяти
  • ENOTCONN: Сокет, связанный с ориентированным на соединение, еще не был подключен
  • ENOTSOCK: Индекс сокета не является сокетом. Когда возвращаемое значение равно 0, соединение закрывается нормально.

специальные

Когда возвращаемое значение <0 и (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN), соединение считается нормальным и прием продолжается.

EAGAIN, EWOULDBLOCK, EINTR и неблокирование

  • EWOULDBLOCK: Для неблокирующего режима нет необходимости читать или писать снова
  • EINTR: Указывает на то, что операция была вызвана прерыванием и должна быть снова прочитана / записана.

Если происходит EINTR, то есть значение errno равно 4, ошибка описывает прерванный системный вызов, и операция должна продолжаться.

  • EAGAIN: Linux-неблокирующее программирование сокетов обрабатывает ошибки EAGAIN

Ресурс, временно недоступный, часто возникает при получении данных в неблокирующем сокете в Linux, а код ошибки равен 11 (EAGAIN). Буквально, это подсказка, чтобы попробовать еще раз. Эта ошибка часто возникает, когда приложение выполняет некоторые неблокирующие операции (над файлами или сокетами). Эта ошибка не нарушит синхронизацию сокета, независимо от этого, следующий цикл может быть восстановлен.

Для неблокирующих сокетов EAGAIN не является ошибкой. В VxWorks и Windows имя EAGAIN — EWOULDBLOCK.

Например, откройте файл / socket / FIFO с флагом O_NONBLOCK, если вы выполняете операции чтения непрерывно и данные не могут быть прочитаны. На этом этапе программа не будет блокироваться, пока данные не будут готовы к возврату. Функция чтения вернет ошибку EAGAIN, указывающую, что у вашего приложения нет данных для чтения. Повторите попытку позже.

В другом примере, когда системный вызов (такой как fork) не выполняется из-за нехватки ресурсов (например, виртуальной памяти), верните EAGAIN, чтобы запросить повторный вызов (возможно, в следующий раз это произойдет).

Ссылка:

https://segmentfault.com/a/1190000003780387

https://blog.csdn.net/haluoluo211/article/details/48381649

https://blog.csdn.net/wm_1991/article/details/51858997

socket_recv

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

socket_recvПолучает данные из подсоединённого сокета

Описание

int socket_recv
( resource $socket
, string &$buf
, int $len
, int $flags
)

Параметр buf передаётся по ссылке, так что он должен быть
указан в виде переменной в списке аргументов. Данные, прочитанные из сокета
socket функцией socket_recv(),
будут возвращены в параметре buf.

Список параметров

socket

Параметр socket должен быть ресурсом сокета,
предварительно созданным при помощи функции socket_create().

buf

Полученные данные будут переданы в переменную, указанную в параметре
buf. Если происходит ошибка, если соединение
сброшено, или если данные недоступны, параметр
buf будет установлен в NULL.

len

До len байт будет получено с удалённого хоста.

flags

Значение параметра flags может быть любой
комбинацией следующих флагов, соединённых при помощи двоичного оператора OR (|).

Possible values for flags

Флаг Описание
MSG_OOB Обрабатывать внеполосные (out-of-band) данные.
MSG_PEEK Получать данные с начала очереди получения без
удаления их из очереди.
MSG_WAITALL Функция будет блокировать выполнение скрипта до тех пор, пока как
минимум len байт не будет получено.
Однако, в том случае, если получен сигнал или удалённый хост отсоединился,
функция может вернуть меньше данных.
MSG_DONTWAIT Если этот флаг установлен, то функция вернётся даже в том случае,
если бы она обычно блокировала исполнение скрипта.

Возвращаемые значения

socket_recv() возвращает количество полученных байтов,
или FALSE в случае ошибки. Фактический код ошибки может быть получен при помощи
функции socket_last_error(). Этот код ошибки может быть
передан функции socket_strerror() для получения текстового
описания ошибки.

Примеры

Пример #1 Пример использования socket_recv()

Этот пример — просто вариант первого примера из статьи
Примеры с использованием
socket_recv().


<?php
error_reporting
(E_ALL);

echo 

"<h2>Соединение TCP/IP</h2>n";/* Получить порт сервиса WWW. */
$service_port getservbyname('www''tcp');/* Получить IP-адрес целевого хоста. */
$address gethostbyname('www.example.com');/* Создать сокет TCP/IP. */
$socket socket_create(AF_INETSOCK_STREAMSOL_TCP);
if (
$socket === false) {
    echo 
"Не удалось выполнить функцию socket_create(): причина: " socket_strerror(socket_last_error()) . "n";
} else {
    echo 
"OK.n";
}

echo 

"Попытка соединиться с хостом '$address' по порту '$service_port'...";
$result socket_connect($socket$address$service_port);
if (
$result === false) {
    echo 
"Не получилось выполнить функцию socket_connect().nПричина: ($result) " socket_strerror(socket_last_error($socket)) . "n";
} else {
    echo 
"OK.n";
}
$in "HEAD / HTTP/1.1rn";
$in .= "Host: www.example.comrn";
$in .= "Connection: Closernrn";
$out '';

echo 

"Отправка запроса HTTP HEAD...";
socket_write($socket$instrlen($in));
echo 
"OK.n";

echo 

"Получение ответа:nn";
$buf 'Это мой буфер.';
if (
false !== ($bytes socket_recv($socket$buf2048MSG_WAITALL))) {
    echo 
"Прочитано $bytes байта из функции socket_recv(). Закрываем сокет...";
} else {
    echo 
"Не получилось выполнить socket_recv(); причина: " socket_strerror(socket_last_error($socket)) . "n";
}
socket_close($socket);

echo 

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

Пример выше выведет что-то вроде следующего:

<h2>TCP/IP Connection</h2>
OK.
Попытка соединиться с хостом '208.77.188.166' on port '80'...OK.
Отправка запроса HTTP HEAD...OK.
Получение ответа:

Прочитано 123 байта из функции socket_recv(). Закрываем сокет...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.

Вернуться к: Сокетные Функции

 By default a socket is configured so that sending or receiving data blocks, stopping program execution until the socket is ready (setblocking(1)). Calls to send() wait for buffer space to be available for the outgoing data, and calls to recv() wait for the other program to send data that can be read. This form of I/O operation is easy to understand, but can lead to inefficient operation and even deadlocks, if both programs end up waiting for the other to send or receive data.

There are a few ways to work around this situation. One is to use a separate thread for communicating with each socket. This can introduce other complexities, though, with communication between the threads.

Another option is to change the socket to not block at all, and return immediately if it is not ready to handle the operation. Use the setblocking() method to change the blocking flag for a socket. The default value is 1, which means to block. Passing a value of 0 turns off blocking. If the socket is has blocking turned off and it is not ready for the operation, then socket.error is raised.

A compromise solution is to set a timeout value for socket operations. Use settimeout() to change the timeout of a socket to a floating point value representing the number of seconds to block before deciding the socket is not ready for the operation. When the timeout expires, a timeout exception is raised.

In the case of a non blocking socket that has no data available, recv
will throw the socket.error exception and the value of the exception
will have the errno of either EAGAIN or EWOULDBLOCK.


import sys
import socket
import fcntl, os
import errno
from time import sleep

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
fcntl.fcntl(s, fcntl.F_SETFL, os.O_NONBLOCK)

while True:
    try:
        msg = s.recv(4096)
    except socket.error, e:
        err = e.args[0]
        if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
            sleep(1)
            print 'No data available'
            continue
        else:
            # a "real" error occurred
            print e
            sys.exit(1)
    else:
        # got a message, do something :)

The situation is a little different in the case where you’ve enabled non-blocking behavior via a time out with s.settimeout(n)


import sys
import socket
from time import sleep

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
s.settimeout(2)

while True:
    try:
        msg = s.recv(4096)
    except socket.timeout, e:
        err = e.args[0]
        # this next if/else is a bit redundant, but illustrates how the
        # timeout exception is setup
        if err == 'timed out':
            sleep(1)
            print 'recv timed out, retry later'
            continue
        else:
            print e
            sys.exit(1)
    except socket.error, e:
        # Something else happened, handle error, exit, etc.
        print e
        sys.exit(1)
    else:
        if len(msg) == 0:
            print 'orderly shutdown on server end'
            sys.exit(0)
        else:
            # got a message do something :) 

But remember The socket.makefile() docs say, «the socket must be in blocking mode.

sock.settimeout(None)

Another method:


import select

mysocket.setblocking(0)

ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
    data = mysocket.recv(4096)

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Socket protect error openvpn mac
  • Socket processaccept error too many open files
  • Socket port bind error
  • Socket io unhandled error event
  • Socket io transport error

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии