recv、recvfrom、recvmsg以及send、sendto、sendmsg

  • 一. recv、recvfrom、recvmsg函数
  • 1.函数原型
  • 二. send、sendto、sendmsg函数
  • 1.函数原型


一. recv、recvfrom、recvmsg函数

这几个函数都是从套接字读入数据,recvfrom和recvmsg用来在一个面向连接或非连接的套接口上接收数据,recv一般用在建立连接connect的套接字。

1.函数原型

#include <sys/types.h>
       #include <sys/socket.h>

       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

(1)recv函数和recvmsg函数的前四个参数都是一样的:

sockfd 套接字描述符

buf 读入缓冲区

len 缓冲区接收字节的长度

flags 一般为0或为下图参数

recvfrom函数程序 recvfrom函数原型_linux


src_addr 接收对端的ip地址结构

addrlen 对端的ip地址结构长度

(2)resmsg函数调用使用msghdr结构最小化了需要直接提供的参数个数。结构体原型如下:

/*结构体原型*/
		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 */
		    size_t        msg_controllen; /* ancillary data buffer len */
		    int           msg_flags;      /* flags on received message */
		};

如果socket是未连接的,则msg_name 和 msg_namelen指定源地址;如果没有names(地址)需要或请求的话,msg_name可以为null指针。msg_iov 和 msg_iovlen域描述了scatter-gather位置。msg_control域指向存取协议控制相关消息或者辅助数据的一个缓冲,长度为msg_controllen域指定。recvmsg()被调用时,msg_controllen 应该包含msg_control中可用数据长度;如果成果返回,它将设置为控制消息序列长度。

这些消息有如下形式:

struct cmsghdr {

socklen_t cmsg_len; /* 数据字节数,包括hdr头本身 /
int cmsg_level; /
产生协议 /
int cmsg_type; /
协议指定类型 /
/
接下来是数据

unsigned char cmsg_data[]; */

};

辅助数据应该只使用cmsg(3)中定义的宏访问。

flags:在使用recvmsg函数是会将flags传递到msg_flags中;其参数情况如下

MSG_EOR

指示记录边界;收到的数据完成了一个记录(通常在SOCK_SEQPACKET类型套接口中使用)。

MSG_TRUNC

表明数据报的尾部被丢弃了,因为数据报比提供的缓冲大。

MSG_CTRUNC

表明一些控制数据被丢弃了,因为没有更多的空间存储辅助数据。

MSG_OOB

返回表明收到了紧急或带外数据。

MSG_ERRQUEUE

表明没有收到数据,但从套接口错误队列中收到了一个扩展的错误。

recvfrom函数程序 recvfrom函数原型_linux_02


返回值,若成功返回读入的字节数,失败返回-1。

如果套接口上没有消息可读,那么这几个receives调用就等待一个消息到达,除非这个套接口被设置为非阻塞的,在这种情况下调用返回-1并且外部变量errno被设置为EAGAIN或EWOULDBLOCK。这几个receives调用通常返回当前已有的数据(当然最多是你请求的量),而不是等待所有请求的数据量。


二. send、sendto、sendmsg函数

这几个函数都是发送消息。但是send只可用于基于连接connect的套接字,send 和 write唯一的不同点是标志的存在,当标志为0时,send等同于write。sendto 和 sendmsg既可用于无连接的套接字,也可用于基于连接的套接字。除了套接字设置为非阻塞模式,调用将会阻塞直到数据被发送完。

1.函数原型

#include <sys/types.h>
       #include <sys/socket.h>

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);

       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

       ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

sock:索引将要从其发送数据的套接字。
buf:指向将要发送数据的缓冲区。
len:以上缓冲区的长度。
flags:是以下零个或者多个标志的组合体,可通过or操作连在一起

MSG_DONTROUTE:不要使用网关来发送封包,只发送到直接联网的主机。这个标志主要用于诊断或者路由程序。
MSG_DONTWAIT:操作不会被阻塞。
MSG_EOR:终止一个记录。
MSG_MORE:调用者有更多的数据需要发送。
MSG_NOSIGNAL:当另一端终止连接时,请求在基于流的错误套接字上不要发送SIGPIPE信号。
MSG_OOB:发送out-of-band数据(需要优先处理的数据),同时现行协议必须支持此种操作。

dest_addr:指向存放接收端地址的区域,可以为NULL。
addrlen:以上内存区的长度,可以为0。
msg:指向存放发送消息头的内存缓冲,和recvmsg函数中第二参数一致。
成功执行时,返回已发送的字节数。失败返回-1,errno被设为的某个值