(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP
socket_recv — Receives 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 tonull
. -
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
}
?>
Содержание
- socket_recv — Получает данные из подсоединённого сокета
- Описание
- Список параметров
- Возвращаемые значения
- Примеры
- Соединение TCP/IP
- recv function (winsock.h)
- Syntax
- Parameters
- Return value
- Remarks
- Example Code
- Example Code
- Функция recv (winsock.h)
- Синтаксис
- Параметры
- Возвращаемое значение
- Комментарии
- Пример кода
- Пример кода
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:
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);
Описание параметра
- Первый параметр указывает дескриптор получающего сокета;
- Второй параметр указывает буфер, который используется для хранения данных, полученных функцией recv;
- Третий параметр указывает длину буфера;
- Четвертый параметр обычно устанавливается на ноль.
Процесс выполнения функции recv синхронного сокета
Когда приложение вызывает функцию recv:
- Сначала recv ожидает передачи данных в буфере отправки SOCKET по протоколу.доставитьПри отправке данных в сПроизошла ошибка сетиЗатем функция recv возвращаетSOCKET_ERROR;
- Если сОтправить буфервНет данныхилиДанные были успешно отправлены по протоколуПосле recvСначала проверьте приемный буфер сокета s;
- Если сПриемный буфервНет данныхилиПротокол получения данныхТогда recv былПодождитеПока протокол не получил данные;
- Когда протокол завершил получение данных, функция recvПриемный буферДанные вскопировать в буферДюйм (Обратите внимание, что данные, полученные протоколом, могут быть больше, чем длина буфера, поэтому в этом случае функцию recv необходимо вызывать несколько раз, чтобы скопировать данные в приемный буфер функции s. RecvПросто скопируйте данныеФактический прием данных осуществляется протоколом.) Функция recv возвращает количество байтов, которые она фактически скопировала. Если ошибки recv при копировании, то он возвращаетSOCKET_ERROR;
- Если функция recv находится вОтказ сети при ожидании протокола для получения данныхВверх, то этоВозвращает 0.
Сокет по умолчанию является блокирующим. Нет никакого различия между блокирующими и неблокирующими возвращаемыми значениями recv, оба<0 ошибка = 0 соединение закрыто> 0 получен размер данных.
Возвращаемое значение
- После успешного выполнения возвращается количество полученных байтов.
- Возвращает 0, если другой конец закрыт.
- -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_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);
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)