recv 函式 (winsock.h)
recv函式會從連接的通訊端或系結的無連線通訊端接收資料。
語法
int recv(
[in] SOCKET s,
[out] char *buf,
[in] int len,
[in] int flags
);
參數
[in] s
識別已連線通訊端的描述項。
[out] buf
要接收傳入資料的緩衝區指標。
[in] len
buf參數所指向之緩衝區的長度,以位元組為單位。
[in] flags
一組旗標,會影響此函式的行為。 請參閱下面的<備註>。 如需此參數可能值的詳細資訊,請參閱一節。
傳回值
如果沒有發生錯誤, recv 會傳回收到的位元組數,而 buf 參數所指向的緩衝區將包含所接收的資料。 如果連線已正常關閉,則傳回值為零。
否則,會傳回SOCKET_ERROR的值,而且可以呼叫 WSAGetLastError來擷取特定的錯誤碼。
錯誤碼 | 意義 |
---|---|
使用此函式之前,必須先進行成功的 WSAStartup 呼叫。 | |
網路子系統失敗。 | |
buf參數並未完全包含在使用者位址空間的有效部分。 | |
未連接此通訊端。 | |
(封鎖) 呼叫已透過 WSACancelBlockingCall取消。 | |
封鎖的 Windows Sockets 1.1 呼叫正在進行中,或者服務提供者仍在處理回呼函式。 | |
針對連線導向通訊端,此錯誤表示連線已因在作業進行時偵測到失敗的 保持 運作活動而中斷。 如果是資料包通訊端,此錯誤表示已超過存留時間。 | |
描述項不是通訊端。 | |
已指定MSG_OOB,但通訊端不是資料流程樣式,例如類型SOCK_STREAM、與此通訊端相關聯的通訊網域不支援 OOB 資料,或通訊端是單向的,而且只支援傳送作業。 | |
通訊端已關閉; 在關閉 之後,無法使用 設定 為 SD_RECEIVE 或 SD_BOTH 來叫用通訊端上的接收。 | |
通訊端標示為非封鎖,而接收作業會封鎖。 | |
訊息太大而無法放入指定的緩衝區,且已截斷。 | |
通訊端尚未系結系 結,或指定未知旗標,或已針對已啟用SO_OOBINLINE的通訊端指定MSG_OOB,或只針對位元組資料流程通訊端指定 (,) len 為零或負數。 | |
此虛擬電路由於逾時或其他錯誤而終止。 此通訊端無法再使用,應用程式應予以關閉。 | |
因為網路錯誤或因為對等系統無法回應,所以此連接已中斷。 | |
執行硬式或失敗關閉的遠端部分已重設此虛擬電路。 此通訊端無法再使用,應用程式應予以關閉。 在 UDP-datagram 通訊端上,此錯誤表示先前的傳送作業導致 ICMP「無法連線埠」訊息。 |
備註
recv函式可用來讀取連線導向通訊端或無連接通訊端上的傳入資料。 使用連接導向通訊協定時,必須先連接通訊端,才能呼叫 recv。 使用無連線通訊協定時,必須先系結通訊端,才能呼叫 recv。
必須知道通訊端的本機位址。 針對伺服器應用程式,請使用明確的 系結 函式或隱含 接受 或 WSAAccept 函式。 用戶端應用程式不建議使用明確系結。 針對用戶端應用程式,通訊端可以使用 connect、 WSAConnect、 sendto、 WSASendTo或 WSAJoinLeaf隱含地系結至本機位址。
針對連線或無連線通訊端, recv 函式會限制接受接收訊息的來源位址。 函式只會從連接中指定的遠端位址傳回訊息。 其他位址的訊息 (會以無訊息方式) 捨棄。
對於連線導向通訊端 (類型SOCK_STREAM例如) ,呼叫 recv 會傳回目前可用的資料量,最多可傳回指定的緩衝區大小。 如果通訊端已針對 OOB 資料的內嵌接收設定, (通訊端選項SO_OOBINLINE) 且 OOB 資料尚未讀取,則只會傳回 OOB 資料。 應用程式可以使用 ioctlsocket 或 WSAIoctlSIOCATMARK 命令來判斷是否要讀取任何其他 OOB 資料。
對於無連線通訊端 (類型SOCK_DGRAM或其他訊息導向通訊端) ,資料會從 連線 函式所指定的目的地位址擷取第一個排入佇列的資料包 (訊息) 。
如果資料包或訊息大於指定的緩衝區,則緩衝區會填入資料包的第一個部分,而 recv 會產生錯誤 WSAEMSGSIZE。 例如,針對不可靠的通訊協定 (,UDP) 過多的資料會遺失;對於可靠的通訊協定,資料會由服務提供者保留,直到呼叫具有足夠大緩衝區 的 recv 成功讀取為止。
如果通訊端沒有可用的傳入資料, 則 recv 呼叫會封鎖並等候資料根據針對 WSARecv 所定義的封鎖規則,且未設定MSG_PARTIAL旗標,除非通訊端為非封鎖。 在此情況下,會傳回值 SOCKET_ERROR,並將錯誤碼設定為 WSAEWOULDBLOCK。 select、WSAAsyncSelect或WSAEventSelect函式可用來判斷更多資料送達的時間。
如果通訊端是連線導向,而遠端端已正常關閉連線,而且已接收所有資料, 則 recv 會立即完成,並接收零個位元組。 如果已重設連線, recv 將會失敗,並出現 WSAECONNRESET錯誤。
flags參數可用來影響函式調用的行為,超出針對相關聯通訊端所指定選項。 此函式的語意取決於通訊端選項和 flags 參數。 旗標參數的可能值是使用位 OR 運算子搭配下列任何值來建構。
值 | 意義 |
---|---|
MSG_PEEK | 查看傳入的資料。 資料會複製到緩衝區,但不會從輸入佇列中移除。 |
MSG_OOB | 處理頻外 (OOB) 資料。 |
MSG_WAITALL | 只有在發生下列其中一個事件時,接收要求才會完成:
|
範例程式碼
下列程式碼範例顯示 recv 函式的使用。#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")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int __cdecl main() {
//----------------------
// Declare and initialize variables.
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_port = htons( 27015 );
//----------------------
// Connect to server.
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if ( iResult == SOCKET_ERROR) {
closesocket (ConnectSocket);
printf("Unable to connect to server: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
範例程式碼
如需詳細資訊,以及recv函式的另一個範例,請參閱使用 Winsock 消費者入門。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 |
標頭 | winsock.h (包含 Winsock2.h) |
程式庫 | Ws2_32.lib |
Dll | Ws2_32.dll |