recvfrom()

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

基本介紹

  • 中文名:recvfrom()
  • 作用:接收一個數據報並保存源地址
  • 類型:socket
  • 支持協定:UDP/TCP
函式簡介,注釋,詳細介紹,其他函式比較,注意事項,

函式簡介

接收一個數據報並保存源地址。(這裡是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 卻有數據的現象。

相關詞條

熱門詞條

聯絡我們