sendmsg(2)與recvmsg(2)函數
這些函數為程式提供了一些其他的套介面I/O介面所不具備的進階特性。下面的內容我們將會先來看一下sendmsg來介紹這些主題。然後將會完整的介紹recvmsg函數,因為他們的函數介面是相似的。接下來,將會描述msghdr的完整結構。
sendmsg(2)函數
現在是時候進入這個大同盟了。從概念上說,sendmsg函數是所有寫入函數的基礎,而他是從屬於套介面的。下面的列表以複雜增加的順序列出了所有與入函數。在每一個層次上,同時列出了所增加的特性。
函數 增加的特性
write 最簡單的套介面寫入函數
send 增加了flags標記
sendto 增加了套介面地址與套介面長度參數
writev 沒有標記與套介面地址,但是具有分散寫入的能力
sendmsg 增加標記,套介面地址與長度,分散寫入以及附屬資料的能力
sendmsg(2)函數原型如下:
#include
#include
int sendmsg(int s, const struct msghdr *msg, unsigned int flags);
函數參數描述如下:
要在其上發送訊息的套介面s
資訊頭結構指標msg,這會控制函數調用的功能
可選的標記位參數flags。這與send或是sendto函數調用的標記參數相同。
函數的傳回值為實際發送的位元組數。否則,返回-1表明發生了錯誤,而errno表明錯誤原因。
recvmsg(2)函數
recvmsg是與sendmsg函數相對的函數。這個函數原型如下:
#include
#include
int recvmsg(int s, struct msghdr *msg, unsigned int flags);
函數參數如下:
要在其上接收資訊的套介面s
資訊頭結構指標msg,這會控制函數調用的操作。
可選標記位參數flags。這與recv或是recvfrom函數調用的標記參數相同。
這個函數的傳回值為實際接收的位元組數。否則,返回-1表明發生了錯誤,而errno表明錯誤原因。
理解struct msghdr
當我第一次看到他時,他看上去似乎是一個需要建立的巨大的結構。但是不要怕。其結構定義如下:
struct msghdr {
void *msg_name;
socklen_t msg_namelen;
struct iovec *msg_iov;
size_t msg_iovlen;
void *msg_control;
size_t msg_controllen;
int msg_flags;
};
結構成員可以分為四組。他們是:
套介面地址成員msg_name與msg_namelen。
I/O向量引用msg_iov與msg_iovlen。
附屬資料緩衝區成員msg_control與msg_controllen。
接收資訊標記位msg_flags。
在我們將這個結構分為上面的幾類以後,結構看起來就不那樣巨大了。
成員msg_name與msg_namelen
這些成員只有當我們的套介面是一個資料報套介面時才需要。msg_name成員指向我們要發送或是接收資訊的套介面地址。成員msg_namelen指明了這個套介面地址的長度。
當調用recvmsg時,msg_name會指向一個將要接收的地址的接收地區。當調用sendmsg時,這會指向一個資料報將要發送到的目的地址。
注意,msg_name定義為一個(void *)資料類型。我們並不需要將我們的套介面地址轉換為(struct sockaddr *)。
成員msg_iov與msg_iovlen
這些成員指定了我們的I/O向量數組的位置以及他包含多少項。msg_iov成員指向一個struct iovec數組。我們將會回憶起I/O向量指向我們的緩衝區。成員msg_iov指明了在我們的I/O向量數組中有多少元素。
成員msg_control與msg_controllen
這些成員指向了我們附屬資料緩衝區並且表明了緩衝區大小。msg_control指向附屬資料緩衝區,而msg_controllen指明了緩衝區大小。
成員msg_flags
當使用recvmsg時,這個成員用於接收特定的標記位(他並不用於sendmsg)。在這個位置可以接收的標記位如下表所示:
標記位 描述
MSG_EOR 當接收到記錄結尾時會設定這一位。這通常對於SOCK_SEQPACKET套介面類型十分有用。
MSG_TRUNC 這個標記位表明資料的結尾被截短,因為接收緩衝區太小不足以接收全部的資料。
MSG_CTRUNC 這個標記位表明某些控制資料(附屬資料)被截短,因為緩衝區太小。
MSG_OOB 這個標記位表明接收了帶外資料。
MSG_ERRQUEUE 這個標記位表明沒有接收到資料,但是返回一個擴充錯誤。
我們可以在recvmsg(2)與sendmsg(2)的man手冊頁中查看更多的資訊。
附屬資料結構與宏
recvmsg與sendmsg函數允許程式發送或是接收附屬資料。然而,這些額外的資訊受限於一定的格式規則。這一節將會介紹控制資訊頭與程式將會用來管理這些資訊的宏。