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

參數所指向緩衝區大小的選擇性指標,以位元組為單位。

傳回值

如果沒有發生錯誤, recvfrom 會傳回收到的位元元組數目。 如果連接已正常關閉,則傳回值為零。 否則,會傳回SOCKET_ERROR的值,並呼叫 WSAGetLastError 來擷取特定的錯誤碼。

錯誤碼 意義
WSANOTINITIALISED
使用這個函式之前,必須先進行成功的 WSAStartup 呼叫。
WSAENETDOWN
網路子系統失敗。
WSAEFAULT
buffrom 參數所指向的緩衝區不在使用者位址空間中,或 fromlen 參數太小,無法容納對等位址的來源位址。
WSAEINTR
(封鎖) 呼叫已透過 WSACancelBlockingCall 取消。
WSAEINPROGRESS
封鎖的 Windows Sockets 1.1 呼叫正在進行中,或服務提供者仍在處理回呼函式。
WSAEINVAL
套接字尚未與 結系結,或已指定未知旗標,或已針對已啟用SO_OOBINLINE的套接字指定MSG_OOB,或只針對位元組數據流樣式套接字指定 (,) 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 函式會讀取連線和未連線套接字上的傳入數據,並擷取數據從中傳送的位址。 此函式通常與無連接套接字搭配使用。 必須知道套接字的本機位址。 對於伺服器應用程式,這通常是透過 系結明確完成。 用戶端應用程式不建議使用明確系結。 對於使用此函式的用戶端應用程式,套接字可以透過 sendtoWSASendToWSAJoinLeaf 隱含地系結至本機位址。

對於串流導向套接字,例如類型為 SOCK_STREAM的套接字, 對 recvfrom 的呼叫會傳回目前可用的資訊量,最多可傳回指定的緩衝區大小。 如果套接字已設定為內嵌接收 OOB 資料 (套接字選項SO_OOBINLINE) 且 OOB 數據尚未讀取,則只會傳回 OOB 數據。 應用程式可以使用 ioctlsocketWSAIoctlSIOCATMARK 命令來判斷是否要讀取任何 OOB 資料。 連接導向套接字會忽略 fromfromlen 參數。

針對訊息導向套接字,數據會從第一個加入佇列的訊息擷取,最多可擷取到指定的緩衝區大小。 如果數據報或訊息大於指定的緩衝區,則緩衝區會填入數據報的第一個部分,而 recvfrom 會產生錯誤 WSAEMSGSIZE。 例如,對於不可靠的通訊協定 (,UDP) 多餘的數據會遺失。 如果收到的封包不包含空白 () 的數據, 則來自 recvfrom 函 式的傳回值為零。

如果 from 參數為非零,且套接字不是連線導向, (類型SOCK_DGRAM例如) ,則傳送數據的對等網路位址會複製到對應的 sockaddr 結構。 fromlen 所指向的值會初始化為此結構的大小,並在傳回時加以修改,以指出儲存在 sockaddr 結構中之地址的實際大小。

如果套接字上沒有可用的傳入數據, recvfrom 函式會封鎖並等候數據根據 WSARecv 所定義的封鎖規則來抵達,除非套接字未封鎖,否則不會設定MSG_PARTIAL旗標。 在此情況下,會傳回 SOCKET_ERROR的值,並將錯誤碼設定為 WSAEWOULDBLOCKselectWSAAsyncSelectWSAEventSelect 可用來判斷何時有更多數據送達。

如果套接字是面向連線,而且遠端端已正常關閉連線,則 對 recvfrom 的呼叫將會立即完成,並接收零個字節。 如果連線已重設 recvfrom 將會失敗,並出現 WSAECONNRESET 錯誤。

flags 參數可用來影響函式調用的行為,超出為相關聯套接字指定的選項。 此函式的語意取決於套接字選項和 flags 參數。 後者是使用位 OR 運算元搭配下列任何值來建構。

意義
MSG_PEEK 查看傳入的數據。 數據會複製到緩衝區,但不會從輸入佇列中移除。
MSG_OOB 處理頻外 (OOB) 數據。
 
注意 發出封鎖的 Winsock 呼叫時,例如 recvfrom,Winsock 可能需要等候網路事件,才能完成呼叫。 在此情況下,Winsock 會執行可警示的等候,而異步過程調用 (APC) 排程在相同線程上可能會中斷。 在 APC 內發出另一個封鎖 Winsock 呼叫,中斷相同線程上持續封鎖 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 8 和更新版本上 Windows Phone 市集應用程式支援此函式。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 和更新版本上的 Windows 市集應用程式支援此函式。

規格需求

需求
最低支援的用戶端 Windows 8.1、Windows Vista [傳統型應用程式 |UWP 應用程式]
最低支援的伺服器 Windows Server 2003 [傳統型應用程式 |UWP 應用程式]
目標平台 Windows
標頭 winsock2.h (包含 Winsock2.h)
程式庫 Ws2_32.lib
Dll Ws2_32.dll

另請參閱

WSAAsyncSelect

WSAEventSelect

Winsock 函式

Winsock 參考

recv

send

sockaddr

socket