recv() - Unix、Linux 系統呼叫 - 技術教學
Tutorials Point


  Unix 初學者指南
  Unix Shell 程式設計
  高階 Unix
  Unix 有用參考
  Unix 有用資源
  精選閱讀

版權所有 © 2014 tutorialspoint



  主頁     參考     討論論壇     關於 TP  

recv() - Unix、Linux 系統呼叫


previous next AddThis Social Bookmark Button

廣告

名稱

recv、recvfrom、recvmsg - 從套接字接收訊息

語法

#include <sys/types.h> 

#include <sys/socket.h>

ssize_t recv(int s, void *buf, size_t len, int flags);

ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);

ssize_t recvmsg(int s, struct msghdr *msg, int flags);

描述

recvfrom() 和 recvmsg() 呼叫用於從套接字接收訊息,無論套接字是否面向連線,都可以使用它們來接收資料。

如果 from 不為 NULL,並且底層協議提供源地址,則填充此源地址。引數 fromlen 是一個值-結果引數,初始化為與 from 關聯的緩衝區的尺寸,並在返回時修改以指示儲存在其中的地址的實際尺寸。

recv() 呼叫通常僅在 已連線 的套接字上使用(參見 connect(2)),並且與 from 引數為 NULL 的 recvfrom() 相同。

所有三個例程在成功完成時都返回訊息的長度。如果訊息太長而無法放入提供的緩衝區中,則可能會根據接收訊息的套接字型別丟棄多餘的位元組。

如果套接字上沒有可用的訊息,則接收呼叫將等待訊息到達,除非套接字是非阻塞的(參見 fcntl(2)),在這種情況下,將返回 -1,並且外部變數 errno 設定為 EAGAIN。接收呼叫通常返回任何可用的資料,最多達到請求的數量,而不是等待接收請求的全部數量。

可以使用 select(2) 或 poll(2) 呼叫來確定何時到達更多資料。

recv() 呼叫的 flags 引數是透過對以下一個或多個值進行 OR 運算形成的

標籤描述
MSG_DONTWAIT
 啟用非阻塞操作;如果操作將阻塞,則返回 EAGAIN(這也可以使用 O_NONBLOCKF_SETFL fcntl(2) 結合使用)。
MSG_ERRQUEUE
 此標誌指定應從套接字錯誤佇列中接收排隊的錯誤。錯誤透過輔助訊息傳遞,其型別取決於協議(對於 IPv4 IP_RECVERR)。使用者應提供足夠尺寸的緩衝區。有關更多資訊,請參見 cmsg(3) 和 ip(7)。導致錯誤的原始資料包的有效負載透過 msg_iovec 作為普通資料傳遞。導致錯誤的資料報的原始目標地址透過 msg_name 提供。
對於本地錯誤,不傳遞地址(這可以使用 cmsghdrcmsg_len 成員進行檢查)。對於錯誤接收,在 msghdr 中設定 MSG_ERRQUEUE。傳遞錯誤後,將根據下一個排隊的錯誤重新生成掛起的套接字錯誤,並在下一個套接字操作上傳遞。

錯誤以 sock_extended_err 結構提供

#define SO_EE_ORIGIN_NONE 0 #define SO_EE_ORIGIN_LOCAL 1 #define SO_EE_ORIGIN_ICMP 2 #define SO_EE_ORIGIN_ICMP6 3

struct sock_extended_err { u_int32_t ee_errno; /* error number */ u_int8_t ee_origin; /* where the error originated */ u_int8_t ee_type; /* type */ u_int8_t ee_code; /* code */ u_int8_t ee_pad; u_int32_t ee_info; /* additional information */ u_int32_t ee_data; /* other data */ /* More data may follow */ };

struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

ee_errno 包含排隊錯誤的 errno 編號。ee_origin 是錯誤原始碼。其他欄位是特定於協議的。宏 SOCK_EE_OFFENDER 返回指向錯誤源網路物件的地址的指標,該指標給定指向輔助訊息的指標。如果不知道此地址,則 sockaddrsa_family 成員包含 AF_UNSPEC,並且 sockaddr 的其他欄位未定義。導致錯誤的資料包的有效負載作為普通資料傳遞。
對於本地錯誤,不傳遞地址(這可以使用 cmsghdrcmsg_len 成員進行檢查)。對於錯誤接收,在 msghdr 中設定 MSG_ERRQUEUE。傳遞錯誤後,將根據下一個排隊的錯誤重新生成掛起的套接字錯誤,並在下一個套接字操作上傳遞。
MSG_OOB
 此標誌請求接收帶外資料,這些資料不會在正常資料流中接收。某些協議將快速資料放置在正常資料佇列的頭部,因此此標誌不能與這些協議一起使用。
MSG_PEEK
 此標誌導致接收操作從接收佇列的開頭返回資料,而不會從佇列中刪除該資料。因此,後續的接收呼叫將返回相同的資料。
MSG_TRUNC
 返回資料包的真實長度,即使它比傳遞的緩衝區更長。僅對資料包套接字有效。
MSG_WAITALL
 此標誌請求操作阻塞,直到完全滿足請求。但是,如果捕獲到訊號、發生錯誤或斷開連線,或者要接收的下一個資料與返回的資料型別不同,則呼叫仍可能返回少於請求的資料。
recvmsg() 呼叫使用 msghdr 結構來最大程度地減少直接提供的引數的數量。此結構具有以下形式,如 <sys/socket.h> 中定義的那樣

struct msghdr { void *msg_name; /* optional address */ socklen_t msg_namelen; /* size of address */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data, see below */ socklen_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ };

這裡 msg_namemsg_namelen 指定套接字未連線時的源地址;如果不需要或不需要名稱,則 msg_name 可以指定為 null 指標。欄位 msg_iovmsg_iovlen 描述分散-聚集位置,如 readv(2) 中所述。欄位 msg_control(長度為 msg_controllen)指向其他協議控制相關訊息或雜項輔助資料的緩衝區。當呼叫 recvmsg() 時,msg_controllen 應包含 msg_control 中可用緩衝區的長度;在成功呼叫返回後,它將包含控制訊息序列的長度。
訊息的形式為

struct cmsghdr { socklen_t cmsg_len; /* data byte count, including hdr */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by u_char cmsg_data[]; */ };

輔助資料只能由 cmsg(3) 中定義的宏訪問。
例如,Linux 使用此輔助資料機制透過 Unix 套接字傳遞擴充套件錯誤、IP 選項或檔案描述符。
recvmsg() 返回後,將設定 msghdr 中的 msg_flags 欄位。它可以包含多個標誌
MSG_EOR
 指示記錄結束;返回的資料完成了一個記錄(通常與型別為 SOCK_SEQPACKET 的套接字一起使用)。
MSG_TRUNC
 指示由於資料報大於提供的緩衝區而丟棄了資料報的尾部。
MSG_CTRUNC
 指示由於輔助資料緩衝區空間不足而丟棄了一些控制資料。
MSG_OOB
 返回以指示已接收加速資料或帶外資料。
MSG_ERRQUEUE
 指示未接收資料,但來自套接字錯誤佇列的擴充套件錯誤。

返回值

這些呼叫返回接收到的位元組數,如果發生錯誤則返回 -1。當對等方已執行有序關閉時,返回值將為 0。

錯誤

這些是由套接字層生成的一些標準錯誤。其他錯誤可能會由底層協議模組生成和返回;請參閱其手冊頁。
標籤描述
EAGAIN 套接字被標記為非阻塞,並且接收操作將阻塞,或者已設定接收超時,並且在接收資料之前超時已過期。
EBADF 引數 s 是無效的描述符。
ECONNREFUSED
 遠端主機拒絕允許網路連線(通常是因為它未執行請求的服務)。
EFAULT 接收緩衝區指標指向程序地址空間之外。
EINTR 在任何資料可用之前,接收被訊號傳遞中斷。
EINVAL 傳遞了無效的引數。
ENOMEM 無法為 recvmsg() 分配記憶體。
ENOTCONN
 套接字與面向連線的協議關聯,但尚未連線(參見 connect(2) 和 accept(2))。
ENOTSOCK
 引數 s 不引用套接字。

符合標準

4.4BSD(這些函式呼叫首次出現在 4.2BSD 中),POSIX.1-2001。

POSIX.1-2001 僅描述 MSG_OOBMSG_PEEKMSG_WAITALL 標誌。

備註

上面給出的原型遵循 glibc2。Single Unix 規範與此一致,除了它具有型別為“ssize_t”的返回值(而 4.x BSD 和 libc4 和 libc5 都具有“int”)。flags 引數在 4.x BSD 中為“int”,但在 libc4 和 libc5 中為“unsigned int”。len 引數在 4.x BSD 中為“int”,但在 libc4 和 libc5 中為“size_t”。fromlen 引數在 4.x BSD、libc4 和 libc5 中為“int *”。當前的“socklen_t *”是由 POSIX 發明的。另請參見 accept(2)。

根據 POSIX.1-2001,msghdr 結構的 msg_controllen 欄位應型別化為 socklen_t,但 glibc 當前(2.4)將其型別化為 size_t

另請參見



previous next Printer Friendly

廣告


  

廣告



廣告
© . All rights reserved.