функция recvfrom (winsock.h)

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

Синтаксис

int 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
Сокет не был привязан к bind, или был указан неизвестный флаг, или 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-datagram эта ошибка указывает на то, что предыдущая операция отправки привела к сообщению о недоступности порта 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, WSAsyncSelect или WSAEventSelect .

Если сокет ориентирован на подключение и удаленная сторона корректно завершает подключение, вызов recvfrom будет немедленно завершен с нулевым числом полученных байтов. Если подключение было сброшено 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;
    struct sockaddr_in RecvAddr;

    unsigned short Port = 27015;

    char RecvBuf[1024];
    int BufLen = 1024;

    struct 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 winsock.h (включая Winsock2.h)
Библиотека Ws2_32.lib
DLL Ws2_32.dll

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

WSAsyncSelect

WSAEventSelect

Функции Winsock

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

Recv

send

sockaddr

Сокета