recvmsg
?是 Linux 網絡編程中用于接收消息的高級系統調用,支持復雜數據結構和輔助數據的接收,適用于 TCP/UDP/UNIX 域套接字等場景?。以下是其核心用法詳解:
?1. 函數原型與參數?
#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
- ?
sockfd
?
套接字描述符,需預先通過?socket()
?創建?。 - ?
msg
?
指向?msghdr
?結構體的指針,用于存儲消息的元數據和緩沖區信息(見下文詳細解析)?。 - ?
flags
?
控制接收行為的標志位(如?MSG_PEEK
?預覽數據、MSG_WAITALL
?阻塞直到數據滿緩沖區)?。
?2.?msghdr
?結構體詳解?
struct msghdr {void *msg_name; // 可選:發送方地址(UDP 適用)socklen_t msg_namelen; // 地址長度struct iovec *msg_iov; // 分散/聚集 I/O 緩沖區數組size_t msg_iovlen; // 緩沖區數量void *msg_control; // 輔助數據(如文件描述符)size_t msg_controllen; // 輔助數據長度int msg_flags; // 接收消息的標志(輸出參數)
};
?關鍵字段說明?
- ?
msg_iov
?與?msg_iovlen
?
支持多緩沖區接收數據(分散讀取),通過?iovec
?結構體數組實現:struct iovec {void *iov_base; // 緩沖區起始地址size_t iov_len; // 緩沖區長度 };
buf1
?和?buf2
?。 - ?
msg_control
?與?msg_controllen
?
用于接收輔助數據(如 UNIX 域套接字傳遞的文件描述符),需配合?cmsghdr
?結構體解析?。
?3. 典型應用場景?
?場景1:UDP 接收數據(帶發送方地址)?
struct sockaddr_in sender_addr;
struct msghdr msg = {0};
struct iovec iov;
char buf[1024];iov.iov_base = buf;
iov.iov_len = sizeof(buf);
msg.msg_name = &sender_addr;
msg.msg_namelen = sizeof(sender_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;recvmsg(sockfd, &msg, 0); // 接收數據并獲取發送方地址?:ml-citation{ref="3,5" data="citationList"}
?場景2:接收文件描述符(UNIX 域套接字)?
struct msghdr msg = {0};
struct iovec iov;
char buf?[8192];
int fd; // 接收的文件描述符// 輔助數據緩沖區(需對齊)
union {struct cmsghdr cm;char control[CMSG_SPACE(sizeof(int))];
} control_un;iov.iov_base = buf;
iov.iov_len = sizeof(buf);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);recvmsg(sockfd, &msg, 0);// 解析輔助數據獲取文件描述符
struct cmsghdr *cmptr = CMSG_FIRSTHDR(&msg);
if (cmptr != NULL && cmptr->cmsg_type == SCM_RIGHTS) {fd = *((int *)CMSG_DATA(cmptr)); // 提取描述符?
}
?4. 標志位(flags
)詳解?
標志 | 作用 |
---|---|
MSG_PEEK | 預覽數據但不從接收緩沖區移除(可重復讀取)? |
MSG_WAITALL | 阻塞直到請求的字節數全部接收(TCP 適用)? |
MSG_DONTWAIT | 非阻塞模式,無數據時立即返回?EAGAIN ? |
MSG_TRUNC | 若數據被截斷,通過?msg_flags ?返回該標志(UDP 適用)? |
?5. 錯誤處理?
- ?返回值?
成功時返回接收的字節數,失敗返回?-1
?并設置?errno
(如?EAGAIN
、ECONNRESET
)?。 - ?
msg_flags
?輸出?
接收后可通過?msg.msg_flags
?檢查附加標志(如?MSG_TRUNC
、MSG_CTRUNC
)?。
?6. 性能與擴展性?
- ?優勢?
相比?recv
/recvfrom
,recvmsg
?支持多緩沖區和輔助數據,減少系統調用次數,提升效率?。 - ?限制?
復雜參數需謹慎處理,如?msg_control
?緩沖區未對齊可能導致錯誤?。
此函數廣泛應用于高級網絡編程(如 SCTP 協議、容器通信)和進程間文件描述符傳遞?。