`

recv/send 和 recvmsg/sendmsg 函数

阅读更多
        recv 和 send 函数类似于标准的 read 和 wirte 函数,不过多了一个额外的参数。
#include <sys/socket.h>
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 */

        这两个函数的前三个参数等同于 read 和 write 的 3 个参数,flags 参数的值或为 0,或为下表中的一个或多个常值的逻辑或。

        其中各标志选项的含义如下。
        * MSG_DONTROUTE:告知内核目的主机在某个直接连接的本地网络上,而无需查找路由表。这可使用本标志针对单个输出操作开启,也可使用 SO_DONTROUTE 套接字选项(见通用套接字选项)针对某个给定套接字上的所有输出操作开启。
        * MSG_DONTWAIT:临时将当个 I/O 操作指定为非阻塞。
        * MSG_OOB:对于 send,表示即将发送带外数据;对于 recv,表示即将读入的是带外数据。后面会讲到,TCP 连接上只有一个字节可以作为带外数据发送。
        * MSG_PEEK:适用于 recv 和 recvfrom 函数,它允许我们查看已可读取的数据,而且系统不会在 recv 或 recvfrom 返回后丢弃这些数据。
        * MSG_WAITALL:告知内核不要在尚未读入请求数目的字节前让一个读操作返回。当然,当(a)捕获一个信号,(b)连接被终止,(c)套接字发生错误时仍有可能返回比所请求的字节数要少的数据。
        另有一些标志适用于 TCP/IP 以外的协议族,比如 OSI 的传输层是基于记录的(TCP 是基于字节流),其输出操作支持 MSG_EOR 标志,用于指示逻辑记录的结束。
        最后,这两个函数的 flags 参数都是按值传递的,内核无法向进程传回标志,因此如果一个进程需要由内核更新标志,它就必须调用更为通用的 recvmsg 和 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 msghdr{
    void           *msg_name;        // protocol address
    socklen_t      msg__namelen;     // size of protocol address
    struct iovec   *msg_iov;         // scatter/gather array
    int            msg_iovlen;       // # elements in msg_iov
    void           *msg_control;     // ancillary data (cmsghdr struct)
    socklen_t      msg_controllen;   // length of ancillary data
    int            msg_flags;        // flags returned by recvmsg()
};

        在 msghdr 结构的成员变量之中:
        msg_name 和 msg_namelen 用于套接字未连接的场合(如未连接的 UDP 套接字),msg_name 指向一个套接字地址结构,用来存放接收者(对于 sendmsg)或发送者(对于 recvmsg)的协议地址。如果无需指明协议地址(如对于 TCP 或已连接 UDP 套接字),应将其置为空指针。msg_namelen 对于 sendmsg 是一个值参数,对于 recvmsg 则是一个值-结果参数,表示协议地址的长度。
        msg_iov 和 msg_iovlen 用于指定输入或输出缓冲区数组,类似于 readv 或 writev 的第二个和第三个参数(见 readv/writev 函数及存储映射 I/O)。msg_control 和 msg_controllen 用于指定可选的辅助数据的位置和大小,这会在后面介绍。
        这里还需要区分 recvmsg 和 sendmsg 的 flags 参数和 msghdr 结构的 msg_flags 成员。
        1、只有 recvmsg 使用 msg_flags 成员。在调用 recvmsg 时,flags 参数会被复制到 msg_flags 成员,并由内核使用其值驱动接收处理过程。内核还依据 recvmsg 的结果更新 msg_flags 成员的值。
        2、sendmsg 会忽略 msg_flags 成员,因为它直接使用 flags 参数驱动发送处理过程。这意味着如果想在某个 sendmsg 调用中设置 MSG_DONTWAIT 等标志,要设置的应该是 flags 参数,而非 msg_flags 成员。
        下表汇总了内核为输入和输出函数检查的 flags 参数值以及 recvmsg 可能返回的 msg_flags 成员值。

        其中,内核只检查而不返回前 4 个标志,既检查又返回接下来的 2 个标志,不检查而只返回后 4 个标志。recvmsg 返回的 7 个标志解释如下。
        * MSG_BCAST:它的返回条件是本数据报作为链路层广播收取或者其目的 IP 地址是一个广播地址。它是比用 IP_RECVDSTADDR 套接字选项来判定一个 UDP 数据报是否发往某个广播地址的更好方法。
        * MSG_MCAST:它的返回条件是本数据报作为链路层多播收取。
        * MSG_TRUNC:它的返回条件是本数据报被截断,即内核预备返回的数据超过进程事先分配的空间(所有 iov_len 成员之和)。
        * MSG_CTRUNC:它的返回条件是本数据报的辅助数据被截断,即内核预备返回的辅助数据超过进程事先分配的空间(msg_controllen)。
        * MSG_EOR:它的返回条件是返回数据结束一个逻辑记录。
        * MSG_OOB:它绝不为 TCP 带外数据返回,用于其他协议族(如 OSI)。
        * MSG_NOTIFICATION:它由 SCTP 接收者返回,指示读入的消息是一个事件通知,而不是数据消息。
  • 大小: 13.6 KB
  • 大小: 25.8 KB
分享到:
评论

相关推荐

    Linux IO函数的使用和区别

    Linux系统中的IO函数主要有read、write、recv、send、recvmsg、sendmsg、readv、writev,本篇主要介绍他们的使用以及区别。  read函数:  #include  ssize_t read(int fd,void *buf,size_t count);  read...

    iozone.txt

    在Linux和UNIX中有很多的输入输出函数,有时真是让想跟它攀点关系的菜鸟们束手无策。先来看看都有哪些函数,通过解析与总结,看看能不能让大家能这些函数有个理性的认识,哦,原来是这么回事,也就算我没白花这份闲...

    网络编程教程,很好的一本写linux网络编程书,这是我上传的源码

     9.3 函数比recvmsg和sendmsg  本章小结  第十章 守护进程和超级服务器inetd  10.1 守护进程的原理  10.2 编程实践  10.3 超级服务器inetd的工作原理  10.3.1 超级服务器的概念  10.3.2 超级...

    linux网络编程-宋敬彬-part1

    9.2.5 使用recvmsg()和sendmsg()函数 253 9.3 IO模型 256 9.3.1 阻塞IO模型 256 9.3.2 非阻塞IO模型 257 9.3.3 IO复用 257 9.3.4 信号驱动IO模型 258 9.3.5 异步IO模型 258 9.4 select()函数和pselect...

    linux programming instances网络编程教程 附源代码

    11.4 recvmsg和sendmsg函数 11.5 辅助数据 11.6 本章小结 第12章 多线程编程及网络应用 12.1 基本概念 12.1.1 引入多线程的原因 12.1.2 线程的基本概念 12.1.3 线程的分类 12.2 线程基础 12.2.1 线程的...

    C++教程网《Linux网络编程》视频百度云地址

    read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程...

    linux网络编程

    per-conection) 点对点聊天程序实现 09socket编程(四) 流协议与粘包 粘包产生的原因 粘包处理方案 readn writen 回射客户/服务器 10socket编程(五) read、write与recv、send readline实现 用readline实现回射...

    2018年C++教程网的linux网络编程视频共41集百度云下载链接.rar

    read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程与...

    Linux网络编程 视频 教程

    read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程...

    C++教程网视频:linux网络编程

    read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程...

    c++教程网的linux网络编程视频下载

    read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程...

    [免费]2018年C++教程网的linux网络编程视频百度云下载链接.rar

    read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程...

Global site tag (gtag.js) - Google Analytics