• 套接字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网络编程>

  • 相关阅读:
    聊一聊所谓的B端C化
    NetCore3.1IIS其他网站出现HTTP503无法访问解决办法
    技术方案模板 fn
    技术方案模板
    composer的常用操作(composer 2.2.1)
    thinkphp6: 用validate验证参数合法性(thinkphp 6.0.9/php 8.0.14)
    thinkphp6: 从6.0.9升级(php 8.0.14)到 6.0.10lts版本(php 8.1.1)
    thinkphp6: 自定义配置文件(php 8.1.1 / thinkphp v6.0.10LTS)
    linux(ubuntu21.10):为chrome安装jsonvue(chrome 96)
    thinkphp6:mysql数据库使用事务(php 8.1.1 / thinkphp v6.0.10LTS)
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11749359.html
Copyright © 2020-2023  润新知