recvfrom()

本函式用於從(已連線)套接口上接收數據,並捕獲數據傳送源的地址。

函式簡介

接收一個數據報並保存源地址。(這裡是windows中的頭檔案,Linux的用法在下面的那個實例)

#include <winsock.h>

int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,

struct sockaddr FAR* from, int FAR* fromlen);

s:標識一個已連線套接口的描述字。

buf:接收數據緩衝區。

len:緩衝區長度。

flags:調用操作方式。

from:(可選)指針,指向裝有源地址的緩衝區。

fromlen:(可選)指針,指向from緩衝區長度值。

注釋

本函式用於從(已連線)套接口上接收數據,並捕獲數據傳送源的地址。

對於SOCK_STREAM類型的套接口,最多可接收緩衝區大小個數據。如果套接口被設定為線內接收帶外數據(選項為SO_OOBINLINE),且有帶外數據未讀入,則返回帶外數據。應用程式可通過調用ioctlsocket()的SOCATMARK命令來確定是否有帶外數據待讀入。對於SOCK_STREAM類型套接口,忽略from和fromlen參數。

對於數據報類套接口,佇列中第一個數據報中的數據被解包,但最多不超過緩衝區的大小。如果數據報大於緩衝區,那么緩衝區中只有數據報的前面部分,其他的數據都丟失了,並且recvfrom()函式返回WSAEMSGSIZE錯誤。

若from非零,且套接口為SOCK_DGRAM類型,則傳送數據源的地址被複製到相應的sockaddr結構中。fromlen所指向的值初始化時為這個結構的大小,當調用返回時按實際地址所占的空間進行修改。

如果沒有數據待讀,那么除非是非阻塞模式,不然的話套接口將一直等待數據的到來,此時將返回SOCKET_ERROR錯誤,錯誤代碼是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以獲知何時數據到達。

如果套接口為SOCK_STREAM類型,並且遠端“優雅”地中止了連線,那么recvfrom()一個數據也不讀取,立即返回。如果立即被強制中止,那么recv()將以WSAECONNRESET錯誤失敗返回。

在套接口的所設選項之上,還可用標誌位flag來影響函式的執行方式。也就是說,本函式的語義既取決於套接口選項,也取決於標誌位參數。標誌位可取下列值:

值 意義

MSG_PEEK 查看當前數據。數據將被複製到緩衝區中,但並不從輸入佇列中刪除。

MSG_OOB 處理帶外數據(參見2.2.3節具體討論)。

返回值:

若無錯誤發生,recvfrom()返回讀入的位元組數。如果連線已中止,返回0。否則的話,返回SOCKET_ERROR錯誤,應用程式可通過WSAGetLastError()獲取相應錯誤代碼。

錯誤代碼:

WSANOTINITIALISED:在使用此API之前應首先成功地調用WSAStartup()。

WSAENETDOWN:WINDOWS套接口實現檢測到網路子系統失效。

WSAEFAULT:fromlen參數非法;from緩衝區大小無法裝入端地址。

WSAEINTR:阻塞進程被WSACancelBlockingCall()取消。

WSAEINPROGRESS:一個阻塞的WINDOWS套接口調用正在運行中。

WSAEINVAL:套接口未用bind()進行捆綁。

WSAENOTCONN:套接口未連線(僅適用於SOCK_STREAM類型)。

WSAENOTSOCK:描述字不是一個套接口。

WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM類型的。

WSAESHUTDOWN:套接口已被關閉。當一個套接口以0或2的how參數調用shutdown()關閉後,無法再用recv()接收數據。

WSAEWOULDBLOCK:套接口標識為非阻塞模式,但接收操作會產生阻塞。

WSAEMSGSIZE:數據報太大無法全部裝入緩衝區,故被剪下。

WSAECONNABORTED:由於逾時或其他原因,虛電路失效。

WSAECONNRESET:遠端強制中止了虛電路。

參見:

recv(), send(), socket(), WSAAsyncSelect().

詳細介紹

recvfrom  recvfrom函式(經socket接收數據):

函式原型:int recvfrom(SOCKET s,void *buf,int len,unsigned int flags, struct sockaddr *from,int *fromlen);

相關函式 recv,recvmsg,send,sendto,socket

函式說明:recv()用來接收遠程主機經指定的socket傳來的數據,並把數據傳到由參數buf指向的記憶體空間,參數len為可接收數據的最大長度.參數flags一般設0,其他數值定義參考recv().參數from用來指定欲傳送的網路地址,結構sockaddr請參考bind()函式.參數fromlen為sockaddr的結構長度.

返回值:成功則返回接收到的字元數,失敗返回-1.

錯誤代碼

EBADF 參數s非合法的socket處理代碼

EFAULT 參數中有一指針指向無法存取的記憶體空間。

ENOTSOCK 參數s為一檔案描述詞,非socket。

EINTR 被信號所中斷。

EAGAIN 此動作會令進程阻斷,但參數s的socket為不可阻斷。

ENOBUFS 系統的緩衝記憶體不足

ENOMEM 核心記憶體不足

EINVAL 傳給系統調用的參數不正確。

範例

/*利用socket的UDP client

此程式會連線UDP server,並將鍵盤輸入的字元串傳給server。

UDP server 範例請參考sendto()。

*/

#include<sys/stat.h>

#include<fcntl.h>

#include<unistd.h>

#include<sys/typs.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#define PORT 2345

#define SERVER_IP “127.0.0.1”

main()

{

int s,len;

struct sockaddr_in addr;

int addr_len =sizeof(struct sockaddr_in);

char buffer[256];

/* 建立socket*/

if((s = socket(AF_INET,SOCK_DGRAM,0))<0){

perror(“socket”);

exit(1);

}

/* 填寫sockaddr_in*/

bzero(&addr,sizeof(addr));

addr.sin_family = AF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = inet_addr(SERVER_IP);

while(1){

bzero(buffer,sizeof(buffer));

/* 從標準輸入設備取得字元串*/

len =read(STDIN_FILENO,buffer,sizeof(buffer));

/* 將字元串傳送給server端*/

sendto(s,buffer,len,0,&addr,addr_len);

/* 接收server端返回的字元串*/

len = recvfrom(s,buffer,sizeof(buffer),0,&addr,&addr_len);

printf(“receive: %s”,buffer);

}

}

執行 (先執行udp server 再執行udp client)

hello /*從鍵盤輸入字元串*/

receive: hello /*server端返回來的字元串*/

其他函式比較

與recv()函式的比較:UDP使用recvfrom()函式接收數據,他類似於標準的read(),但是在recvfrom()函式中要指明目的地址。從套接字上接收一個訊息。對於recvfrom ,可同時套用於面向連線的和無連線的套接字。recv一般只用在面向連線的套接字,幾乎等同於recvfrom,只要將recvfrom的第五個參數設定NULL。不管是recv還是recvfrom,都有兩種模式,阻塞和非阻塞,可以通過ioctl函式來設定。阻塞模式是一直等待直到有數據到達,非阻塞模式是立即返回,需要通過訊息,異步事件等來查詢完成狀態。

注意事項

第三個參數:len的值不能小於傳送端的數據長度,否則會出現函式的返回結果(接收長度)為-1,而第二個參數buf 卻有數據的現象。

相關詞條

相關搜尋

熱門詞條

聯絡我們