функция 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.
Код ошибки | Значение |
---|---|
Перед использованием этой функции должен быть выполнен успешный вызов WSAStartup . | |
Произошел сбой сетевой подсистемы. | |
Буфер, на который указывают параметры buf или from , не находится в адресном пространстве пользователя или параметр fromlen слишком мал, чтобы вместить исходный адрес однорангового адреса. | |
Вызов (блокирующий) был отменен через WSACancelBlockingCall. | |
Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова. | |
Сокет не был привязан к bind, или был указан неизвестный флаг, или MSG_OOB был указан для сокета с включенным SO_OOBINLINE или (только для сокетов в стиле потока байтов) значение len равно нулю или отрицательному значению. | |
Сокет подключен. Эта функция не разрешена с подключенным сокетом, независимо от того, является ли сокет ориентированным на подключение или без подключения. | |
Для сокета датаграмм эта ошибка указывает на то, что срок жизни истек. | |
Дескриптор в параметре s не является сокетом. | |
MSG_OOB указано, но сокет не является типом потока, например типом SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, или сокет является однонаправленным и поддерживает только операции отправки. | |
Сокет завершен; Невозможно выполнить восстановление в сокете после вызова завершения работыс параметром SD_RECEIVE или SD_BOTH. | |
Сокет помечается как неблокировочный, и операция recvfrom будет блокироваться. | |
Сообщение было слишком большим, чтобы поместиться в буфер, на который указывает параметр buf , и было усечено. | |
Подключение было прервано из-за сбоя сети или из-за того, что система на другом конце не работает без уведомления. | |
Виртуальное подключение было сброшено удаленной стороной путем прерывания. Приложение должно закрыть сокет; он больше недоступен. В сокете 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). |
Пример кода
В следующем примере показано использование функции 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 |