套接字I/O函数write/read writev/readv send/recv sendto/recvfrom sendmsg/recvmsg
函数原型
read/write系原型
1 #include <unistd.h> 2 3 ssize_t read(int fd, void *buf, size_t count);
1 #include <unistd.h> 2 3 ssize_t write(int fd, const void *buf, size_t count);
1 #include <sys/uio.h> 2 3 ssize_t readv(int fd, const struct iovec *iov, int iovcnt); 4 5 ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
send/recv系原型
1 #include <sys/types.h> 2 #include <sys/socket.h> 3 4 ssize_t send(int sockfd, const void *buf, size_t len, int flags); 5 6 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, 7 const struct sockaddr *dest_addr, socklen_t addrlen); 8 9 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
1 #include <sys/types.h> 2 #include <sys/socket.h> 3 4 ssize_t recv(int sockfd, void *buf, size_t len, int flags); 5 6 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, 7 struct sockaddr *src_addr, socklen_t *addrlen); 8 9 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
详细说明
write/read
write用于向任意文件描述符中写入(读取)数据,用作socket发送数据时,只能向已经建立连接的文件描述符中写入(读取)数据;参数以及返回值如下:
1 /** 2 * @fd 文件描述符 3 * @buf 待写入数据缓冲区 4 * @count 请求写入字节数 5 * 成功返回写入字节数,失败返回-1 6 */ 7 ssize_t write(int fd, const void *buf, size_t count);
1 /** 2 * @fd 文件描述符 3 * @buf 读出数据缓冲区 4 * @count 请求读出字节数 5 * 成功返回读取的字节数,0表示读到文件尾,失败返回-1 6 */ 7 ssize_t read(int fd, void *buf, size_t count);
writev/readv
writev向任意文件描述符中写入多个缓冲区的数据,readv用于从任意描述符中向多个缓冲区读取数据,用作socket发送数据时,只能向已经建立连接的文件描述符中写入(读取)数据;参数以及返回值如下:
1 /** 2 * @fd 文件描述符 3 * @iov 多个缓冲区向量 4 * @iovcnt 缓冲区数量 5 * 成功返回写入字节数 失败返回-1 6 */ 7 ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
1 /** 2 * @fd 文件描述符 3 * @iov 多个缓冲区向量 4 * @iovcnt 缓冲区数量 5 * 成功返回读出字节数 失败返回-1 6 */ 7 ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
writev/readv补充说明
writev/readv与write/read功能基本一致,区别在于writev/readv可以写入或者读出指向多个缓冲区;其向量参数iov由多个下面的结构组成,每个结构指向一个缓冲区;
1 struct iovec { 2 void *iov_base; /* Starting address */ 3 size_t iov_len; /* Number of bytes to transfer */ 4 };
send/recv
send用于向socket中写入(读取)数据,只能用于已经建立连接的socket上,udp也可以调用connect建立连接;
1 /** 2 * @sockfd socket文件描述符 3 * @buf 待发送数据缓冲区 4 * @len 请求发送数据字节数 5 * @flags 标志位 6 * 成功返回发送字节数 失败返回-1 7 */ 8 ssize_t send(int sockfd, const void *buf, size_t len, int flags);
1 /** 2 * @sockfd socket文件描述符 3 * @buf 请求接收数据的数据缓冲区 4 * @len 请求接收的字节数 5 * @flags 标志位 6 * 成功返回读取的字节数 失败返回-1 7 */ 8 ssize_t recv(int sockfd, void *buf, size_t len, int flags);
send/recv补充说明
send/recv与write/read的作用基本相同,只是多了一个flag参数,当flag参数设置为0时,它们的功能一致;当sendto/recvfrom函数地址指针为NULL且地址长度为0时,其作用于send/recv一致,实际上内核实现send/recv也是对sendto/recvfrom做了忽略地址信息的简单封装;
sendto/recvfrom
sendto用于向socket中写入(读取)数据,如果用在已经建立连接的socket上,需要忽略其地址和地址长度参数,即地址指针设置为NULL,地址长度设置为0;如udp,如果不调用connec建立连接,则需要指定地址参数,如果调用connect建立了连接,则省略地址参数;
1 /** 2 * @sockfd socket文件描述符 3 * @buf 待写入数据缓冲区 4 * @len 请求写入数据长度 5 * @flags 标志位 6 * @dest_addr 目的地址 7 * @addrlen 地址长度 8 * 成功返回发送字节数 失败返回-1 9 */ 10 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, 11 const struct sockaddr *dest_addr, socklen_t addrlen);
1 /** 2 * @sockfd socket文件描述符 3 * @buf 读取数据的缓冲区 4 * @len 请求读取数据长度 5 * @flags 标志位 6 * @src_addr 源地址 7 * @addrlen 地址长度 8 * 成功返回读取字节数 失败返回-1 9 */ 10 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, 11 struct sockaddr *src_addr, socklen_t *addrlen);
sendto/recvfrom补充说明
当sendto/recvfrom函数地址指针为NULL且地址长度为0时,其作用于send/recv一致,实际上内核实现send/recv也是对sendto/recvfrom做了忽略地址信息的简单封装;
sendmsg/readmsg
sendmsg用于向socket文件描述符中写入多个缓冲区的数据,recvmsg用于向多个缓冲区读取socket文件描述符中的数据,发送(接收)前需要构造msghdr消息头;参数以及返回值如下:
1 /** 2 * @sockfd socket文件描述符 3 * @msg 消息 4 * @标志位 5 */ 6 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
1 /** 2 * @sockfd socket文件描述符 3 * @msg 消息 4 * @标志位 5 */ 6 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
sendmsg/recvmsg补充说明
sendmsg/recvmsg需要构造的消息头部如下,其中msg_iov指向多个iovec,没给iovec对应着一个缓冲区,msg_iovlen标识缓冲区的数量;
1 struct msghdr { 2 void *msg_name; /* optional address */ 3 socklen_t msg_namelen; /* size of address */ 4 struct iovec *msg_iov; /* scatter/gather array */ 5 size_t msg_iovlen; /* # elements in msg_iov */ 6 void *msg_control; /* ancillary data, see below */ 7 socklen_t msg_controllen; /* ancillary data buffer len */ 8 int msg_flags; /* flags on received message */ 9 };
1 struct iovec { 2 void *iov_base; /* Starting address */ 3 size_t iov_len; /* Number of bytes to transfer */ 4 };
函数对比
图片来自<unix网络编程>