高级I/O函数
以下这两个函数是最通用的I/O函数,recvmsg可以代替read, readv, recv 和 recvfrom。 同样,sendmsg可以代替其他的发送函数。
#include < sys/socket.h > ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags) ssize_t sendmsg(int sockfd, struct msghdr * msg, int flags) 返回:成功是为读入或写出的字节数, 出错时为-1 |
以下是参数结构体的描述:
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 */
socklen_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including hdr */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by
unsigned char cmsg_data[]; */
}
1. 首先对struct msghdr结构体进行解释:
msg_name 指向一个套接口地址的结构,msg_namelen是其长度。他和recvfrom ,sendto的第五和第六个参数类似。比如指向一个sockaddr_in结构,里面填充相应的数值。对于sendmsg来说是目的方的协议地址,recvmsg的是发送方的协议地址。
msg_iov 和msg_iovlen成员指明输入或输出的缓冲区数组。举个简单例子,比如我要发送buf1[100],和buf2[50],两个数组(当让也可以是你自定义的结构体),如果发送Udp报文,要发送两次。但可以用msg_iov[2],每个结构体中的iov_base指向各自数组的起始地址,iov_len表示大小。这样发送一个udp报文就可以把这两个数组发送出去。接收也是同样的道理。
我们可以看到函数入口有一个flag,参数结构体里有msg_flags成员。msg_flags只用于recvmsg。调用recvmsg时,flags参数被拷贝到msg_flags成员,内核用这个值进行接受处理。sendmsg会忽略msg_flags成员,因为他在进行输出处理时使用flags参数,比如我们在调用sendmsg成员是设置MSG_DONTWAIT标志,要设置参数flags,而不是msg_flags.
msg_control和msg_controllen成员指明可选的辅助数据的位置和大小,msg_controllen对recvmsg是一个值——结果参数。这个结构体会在其他地方提到。
flags的定义有:可以使多个的或
MSG_DONTROUTE:不要使用网关来发送封包,只发送到直接联网的主机。这个标志主要用于诊断或者路由程序。
MSG_DONTWAIT:操作不会被阻塞。
MSG_EOR:终止一个记录。
MSG_MORE:调用者有更多的数据需要发送。
MSG_NOSIGNAL:当另一端终止连接时,请求在基于流的错误套接字上不要发送SIGPIPE信号。
MSG_OOB:发送out-of-band数据(需要优先处理的数据),同时现行协议必须 支持此种操作。