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或为下图参数
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
表明没有收到数据,但从套接口错误队列中收到了一个扩展的错误。
返回值,若成功返回读入的字节数,失败返回-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被设为的某个值