涉及套接字的I/O操作上设置超时的方法有以下3种。
#include
ssize_t recv(int sockfd, void* buff, size_t nbytes, int flags);
ssize_t send(int sockfd, const void* buff, size_t nbytes, int flags);
返回:若成功则为读入或写成的字节数,若出错则为-1
#include
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
返回:若成功则为读入或写出的字节数,若出错则为-1
这两个函数的第二个参数都是指向某个iovec结构数组的一个指针,其中 iovec 结构在头文件
struct iovec
{
void* iov_base;
size_t iov_len;
};
iovec 结构数组中元素的数目存在某个限制,具体取决于实现。
readv 和 writev 这两个函数可用于任何描述符,而不仅限于套接字。
这两个函数是最通用的I/O函数。
可以把所有 read、readv、recv 和 recvfrom 调用替换成 recvmsg调用。
类似地,各种输出函数调用也可以替换成 sendmsg 调用。
#include
ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr* msg, int flags);
返回:若成功则为读入或写出的字节数,若出错则为-1
这两个函数把大部分参数封装到一个 msghdr 结构中:
struct msghdr
{
void* msg_name; // 对端地址
// 对sendmsg是一个值参数
// 对recvmsg是一个值-结果参数
socklen_t msg_namelen; // 对端地址对象长
struct iovec* msg_iov;
int msg_iovlen;
void* msg_control; // 辅助数据地址
// 对sendmsg是一个值参数
// 对recvmsg是一个值-结果参数
socklen_t msg_controllen;
// recvmsg用其来接收内核处理后标志[来告知应用recvmsg中出现的一些应用可能感兴趣信息]
int msg_flags;
};
辅助数据可通过调用 sendmsg 和 recvmsg 这两个函数,使用 msghdr 结构中的 msg_control 和 msg_controllen 这两个成员发送和接收。
辅助数据的另一个称谓是控制信息。
辅助数据由一个或多个辅助数据对象构成,每个对象以一个定义在头文件
struct cmsghdr
{
socklen_t cmsg_len;
int cmsg_level;
int cmsg_type;
...
};
用于简化对辅助数据的处理。
#include
#include
struct cmsghdr *CMSG_FIRSTHDR(struct msghdr * mhdrptr);
返回:指向第一个 cmsghdr 结构的指针,若无辅助数据则为 NULL
struct cmsghdr *CMSG_NXTHDR(struct msghdr *mhdrptr, struct cmsghdr *cmsgptr);
返回:指向下一个 cmsghdr 结构的指针,若不再有辅助数据对象则为 NULL
unsigned char *CMSG_DATA(struct cmsghdr *cmsgptr);
返回:指向与 cmsghdr 结构关联的数据的第一个字节的指针
unsigned int CMSG_LEN(unsigned int length);
返回:给定数据量下存放到 cmsg_len 中的值
unsigned int CMSG_SPACE(unsigned int length);
返回:给定数据量下一个辅助数据对象总的大小
有3个技术可用于获悉已排队的数据量。
Unix I/O——包括 read、write 这两个函数及它们的变体(recv、send等等)——的函数执行I/O。
这些函数围绕描述符工作,通常作为 Unix 内核中的系统调用实现。
执行I/O的另一个方法是使用标准I/O函数库。
标准I/O函数库可用于套接字,不过需要考虑以下几点。
学习参考资料:
《UNIX网络编程 卷1:套接字联网API》 第3版