Функция recvfrom (winsock2.h)

Функция recvfrom получает датаграмму и сохраняет исходный адрес.

Синтаксис

int WSAAPI recvfrom(
  [in]                SOCKET   s,
  [out]               char     *buf,
  [in]                int      len,
  [in]                int      flags,
  [out]               sockaddr *from,
  [in, out, optional] int      *fromlen
);

Параметры

[in] s

Дескриптор, определяющий привязанный сокет.

[out] buf

Буфер для входящих данных.

[in] len

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

[in] flags

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

[out] from

Необязательный указатель на буфер в структуре sockaddr , который будет содержать исходный адрес при возврате.

[in, out, optional] fromlen

Необязательный указатель на размер (в байтах) буфера, на который указывает параметр from .

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

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

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

Комментарии

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

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

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

Если параметр from не равен нулю и сокет не ориентирован на подключение (например, тип SOCK_DGRAM), сетевой адрес однорангового узла, отправляющего данные, копируется в соответствующую структуру sockaddr . Значение, на которое указывает fromlen , инициализируется размером этой структуры и изменяется при возврате, чтобы указать фактический размер адреса, хранящегося в структуре sockaddr .

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

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

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

Значение Значение
MSG_PEEK Просматривает входящие данные. Данные копируются в буфер, но не удаляются из входной очереди.
MSG_OOB Обрабатывает данные вне диапазона (OOB).
 
Примечание При выполнении блокирующего вызова Winsock, например recvfrom, Winsock может потребоваться дождаться сетевого события, прежде чем вызов сможет завершиться. В этой ситуации Winsock выполняет оповещенное ожидание, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в том же потоке. Выполнение другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению, и клиенты Winsock никогда не должны пытаться его выполнять.
 

Пример кода

В следующем примере показано использование функции recvfrom .
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int main()
{

    int iResult = 0;

    WSADATA wsaData;

    SOCKET RecvSocket;
    sockaddr_in RecvAddr;

    unsigned short Port = 27015;

    char RecvBuf[1024];
    int BufLen = 1024;

    sockaddr_in SenderAddr;
    int SenderAddrSize = sizeof (SenderAddr);

    //-----------------------------------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error %d\n", iResult);
        return 1;
    }
    //-----------------------------------------------
    // Create a receiver socket to receive datagrams
    RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (RecvSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error %d\n", WSAGetLastError());
        return 1;
    }
    //-----------------------------------------------
    // Bind the socket to any address and the specified port.
    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_port = htons(Port);
    RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
    if (iResult != 0) {
        wprintf(L"bind failed with error %d\n", WSAGetLastError());
        return 1;
    }
    //-----------------------------------------------
    // Call the recvfrom function to receive datagrams
    // on the bound socket.
    wprintf(L"Receiving datagrams...\n");
    iResult = recvfrom(RecvSocket,
                       RecvBuf, BufLen, 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
    }
 
    //-----------------------------------------------
    // Close the socket when finished receiving datagrams
    wprintf(L"Finished receiving. Closing socket.\n");
    iResult = closesocket(RecvSocket);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
        return 1;
    }

    //-----------------------------------------------
    // Clean up and exit.
    wprintf(L"Exiting.\n");
    WSACleanup();
    return 0;
}

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

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

Требования

Требование Значение
Минимальная версия клиента Windows 8.1, Windows Vista [классические приложения | Приложения UWP]
Минимальная версия сервера Windows Server 2003 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header winsock2.h (включая Winsock2.h)
Библиотека Ws2_32.lib
DLL Ws2_32.dll

См. также раздел

WSAsyncSelect

WSAEventSelect

Функции Winsock

Справочник по Winsock

Recv

send

sockaddr

Сокета