7.recv()函數族
7.1 包含頭檔案
#include <sys/types.h>
#include <sys/socket.h>
7.2 函數主體
1. ssize_t recv(int sockfd, void *buf, size_t len, int flags);
2. ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
3. ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
參數解釋:
- int sockfd
該參數指明從檔案描述符fd的緩沖區讀取資料。
- void *buf
recv()函數簇讀到的資料将儲存到buf所指向的空間中,用法和read()同理。
- size_t len
該參數指明本次調用接收資料的最大長度。
- int flags
如果flags設定為0,那麼recv()函數和read()沒有任何差別。flags還可以通過OR設定如下參數:
标志位 | 解釋 |
---|---|
MSG_CMSG_CLOEXEC (僅限recvmsg()) | 此flag使用原因通open()中的O_CLOEXEC flag,再socket()中也有介紹,此處不再贅述 |
MSG_DONTWAIT | 設定本次調用為非阻塞,與O_NONBLOCK flag類似,但是該标志為作用域僅限于本次recv調用,而後者則是對檔案描述符操作。 |
MSG_OOB | 此标志指定在正常資料流的接受中不會接收帶外資料。某些協定将加急資料放在正常資料隊列的頭部,是以此标志不能與此類協定一起使用。 |
MSG_PEEK | 此标志指定從接收隊列接收資料,但是不從删除隊列中删除這些資料 |
MSG_TRUNC | 傳回資料報(udp)的實際長度,即使它比傳遞的就收緩沖區更長。注意預設情況下,資料包報無法放入緩沖區時,recv調用會丢棄多餘的位元組 |
MSG_WAITALL | 此标志請求操作阻塞,直到滿足收到的資料滿足請求。 但是,如果信号被捕獲、發生錯誤或斷開連接配接,或者要接收的下一個資料的類型與傳回的資料類型不同,則調用傳回的資料可能仍少于請求的資料。 此标志對資料報套接字沒有影響。 |
- *struct sockaddr src_addr
如果src_addr非NULL,且協定提供消息的源位址,則該源位址将放在 src_addr 所指向的緩沖區中。
-
*socklen_t addrlen
addrlen 是一個value-result參數。在調用之前,應将其初始化為與src_addr關聯的緩沖區的大小。傳回後,addrlen 将更新為包含源位址的實際大小。 如果提供的緩沖區太小,則傳回的位址将被截斷;在這種情況下,addrlen 将傳回一個大于提供給調用的值。
如果不需要知道源位址,則可以将src_addr和addrlen均設為NULL即可。
- struct msghdr *msg
//該結構體如下,等用到時,在進行補充
struct iovec { /* Scatter/gather array items */
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};
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 */
size_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
7.3 傳回值
這些調用傳回收到的位元組數,如果發生錯誤,則傳回 -1。 如果發生錯誤,設定了 errno 用來訓示錯誤。當對端為流套接字且執行關閉函數時,傳回值為0,表示連接配接正常關閉;當對端為流\域套接字時,允許收到是長度為0的資料報。錯誤類型如下(隻列出socket層産生的錯誤,更底層(傳輸層及以下)的錯誤再前面文章種已經全部列出):
錯誤類型 | 解釋 |
---|---|
EAGAIN or EWOULDBLOCK | 設定逾時時間,但在改時間内沒有資料到達 |
EBADF | socket并非有效的檔案描述符 |
ECONNREFUSED | 對端主機拒絕了網絡連接配接 |
EFAULT | buff緩沖區指向非法記憶體 |
EINTR | 在接收資料之前,本次調用被信号中斷 |
EINVAL | 傳遞了無效參數 |
ENOTCONN | socket為面向連接配接套接字,但我沒有成功連接配接 |
ENOTSOCK | socketfd用用的并不是一個socket |