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
從 參數指向之緩衝區大小的選擇性指標,以位元組為單位。
傳回值
如果沒有發生錯誤, recvfrom 會傳回收到的位元元組數目。 如果連線已正常關閉,則傳回值為零。 否則,會傳回SOCKET_ERROR的值,而且可以呼叫 WSAGetLastError 來擷取特定的錯誤碼。
錯誤碼 | 意義 |
---|---|
使用此函式之前,必須先進行成功的 WSAStartup 呼叫。 | |
網路子系統失敗。 | |
buf 或from 參數所指向的緩衝區不在使用者位址空間中,或 fromlen 參數太小,無法容納對等位址的來源位址。 | |
(封鎖) 呼叫已透過 WSACancelBlockingCall 取消。 | |
封鎖的 Windows Sockets 1.1 呼叫正在進行中,或者服務提供者仍在處理回呼函式。 | |
套接字尚未系結系 結,或已指定未知旗標,或已針對已啟用SO_OOBINLINE的套接字指定MSG_OOB,或只針對位元組數據流樣式套接字指定 (,) 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) 過多的數據會遺失。 如果收到的封包不包含空) (數據, 則來自 recvfrom 函式的傳回值為零。
如果 from 參數為非零,且套接字不是連線導向, (類型SOCK_DGRAM例如) ,則傳送數據的對等網路位址會複製到對應的 sockaddr 結構。 fromlen 所指向的值會初始化為這個結構的大小,並在傳回時加以修改,以指出儲存在 sockaddr 結構中之地址的實際大小。
如果套接字沒有可用的傳入數據, 則 recvfrom 函式會封鎖並等候數據根據針對 WSARecv 所定義的封鎖規則,使用未設定MSG_PARTIAL旗標來抵達,除非套接字為非封鎖。 在此情況下,會傳回值 SOCKET_ERROR,並將錯誤碼設定為 WSAEWOULDBLOCK。 選取、WSAAsyncSelect 或 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 8 和更新版本上的 Windows Phone Store 應用程式支援此函式。
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 |
標頭 | winsock.h (包含 Winsock2.h) |
程式庫 | Ws2_32.lib |
Dll | Ws2_32.dll |