C++socket相关IO

本文详细解析了Socket.IO中常用的msghdr、iovec数据结构,以及sendmsg、recvmsg、sendto和recvfrom等发送和接收函数,涵盖了TCP和UDP协议下数据传输的控制选项和灵活操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

socketIO

socketio常用数据结构


  • msghdr

用于描述消息头的结构体,recvmsg,sendmsg中用到

struct msghdr {
    // 可选的地址指针,通常用于存储发送或接收数据的目标地址
    void         *msg_name;       /* 可选的地址 */
    // 地址的长度,与 msg_name 指向的地址结构体大小相匹配
    socklen_t     msg_namelen;    /* 地址大小 */

    // 指向 iovec 结构体数组的指针,用于分散/聚合 I/O 操作
    // 即一次性读取或写入多个缓冲区的数据
    struct iovec *msg_iov;        /* 分散/聚集数组 */
    // iovec 结构体数组中的元素个数
    size_t        msg_iovlen;     /* iovec 数组元素数量 */

    // 指向额外控制信息缓冲区的指针,通常用于携带附加数据,如文件描述符、套接字选项等
    void         *msg_control;    /* 辅助数据,参见下方详细说明 */
    // 辅助数据缓冲区的长度
    socklen_t     msg_controllen; /* 辅助数据缓冲区长度 */

    // 在接收操作时,存储接收到消息的标志,如是否截断、是否有额外控制信息等
    // 在发送操作时,可以设置发送消息的标志
    int           msg_flags;      /* 接收到的消息标志 */
};
  • msg_namemsg_namelen:指向一个可选的地址结构(如sockaddr),以及地址结构的长度。在发送或接收带有源或目标地址信息的消息时使用,对于已连接的套接字通常不需要。

  • msg_iovmsg_iovlen:指向一个iovec结构体数组及其长度,用于分散/聚集I/O操作,可以一次性发送或接收多个缓冲区的数据。

  • msg_controlmsg_controllen:指向附加控制信息(ancillary data)的缓冲区及其长度,可以携带如文件描述符、套接字选项等额外数据。

  • msg_flags:在接收操作中,用于保存接收到的消息的标志;在发送操作中,可以设置发送消息的标志。


  • iovec

用于描述一组缓冲区,常用于分散/聚集I/O操作。允许在一次系统调用中同时读取或写入多个连续或不连续的内存区域。

struct iovec {
    void *iov_base;   /* 开始地址 */
    size_t iov_len;   /* 传送长度 */
};
  • iov_base:指向一个内存区域的指针,该区域将用于读取或写入数据。
  • iov_len:表示这个内存区域的大小,即在I/O操作中要传输的字节数。

使用iovec数组聚集示例

    // 创建两个缓冲区
    char buf1[100];
    char buf2[50];

    // 初始化 iovec 结构体数组
    struct iovec iov[2];
    iov[0].iov_base = buf1;
    iov[0].iov_len = sizeof(buf1);
    iov[1].iov_base = buf2;
    iov[1].iov_len = sizeof(buf2);

    // 设定读取的 iovec 数组元素个数
    int iovcnt = sizeof(iov) / sizeof(struct iovec); // 注意此处假设 iov 已经被正确初始化

    // 使用 readv 一次性读取多个缓冲区的数据
    ssize_t totalBytesRead = readv(fd, iov, iovcnt);
    // 数据已成功读取到 buf1 和 buf2 中,接下来可以处理这些数据...

send recv


send 用于从指定的套接字发送数据。函数原型:

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

参数含义:

  • sockfd:是已连接或已绑定的套接字描述符,用于指定发送数据的通道。
  • buf:指向要发送数据的缓冲区。
  • len:表示要发送数据的字节数。
  • flags:可选的标志,用于控制发送操作的附加行为。常见的标志如 MSG_OOB(发送带外数据),MSG_DONTWAIT(非阻塞发送)等。

此函数会尽可能多地发送缓冲区中的数据,但如果由于网络状况或其他原因没有发送完全部数据,它会返回实际发送的字节数。在遇到错误时,返回值通常为 -1,并设置 errno 来指示具体错误。

在 TCP 协议中,send 函数通常用于发送可靠的数据流。而在 UDP 协议中,send 函数则是发送一个独立的数据报文。


recv ,用于从已连接的套接字接收数据。函数原型如下:

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

参数含义:

  • sockfd:已连接的套接字描述符,标识从哪个套接字接收数据。
  • buf:指向接收缓冲区的指针,接收到的数据将被复制到这个缓冲区内。
  • len:指定接收缓冲区的大小,即期望接收的最大数据量。
  • flags:可选的标志,用于控制接收操作的附加行为。例如:
    • MSG_PEEK:查看数据但不从接收缓冲区移除。
    • MSG_WAITALL:只有在接收缓冲区有足够的数据填满 len 所指定的大小时才返回,否则阻塞等待。
    • MSG_DONTWAIT(或非阻塞模式下的 MSG_NBIO):使 recv 成为非阻塞的,如果没有数据可读,函数会立即返回错误(通常为 EAGAINEWOULDBLOCK)。

recv 函数在成功接收数据时返回接收到的实际字节数,如果连接被关闭或者发生错误,返回值通常为 -1,并设置 errno 来指出具体错误。在没有任何数据可读的情况下(并且未设置 MSG_WAITALL),recv 可能会返回 0,这通常被视为连接已经被优雅地关闭。

sendmsg recvmsg


sendmsg ,用于从套接字发送一个消息,比 send 函数提供更丰富的功能。函数原型:

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

参数含义:

  • sockfd:已连接或已绑定的套接字描述符,指定发送数据的通道。
  • msg:指向 msghdr 结构体的指针,这个结构体包含了要发送的数据及其相关信息。
  • flags:可选的标志,类似于 send 函数中的 flags,用于控制发送行为,如 MSG_DONTWAIT 等。

sendmsg 函数能够在一个系统调用中完成多个操作,如发送数据、附带控制信息等,提高了数据发送的灵活性和效率。尤其在需要发送大量数据或涉及复杂通信场景时,使用 sendmsg 更为便捷。


recvmsg 用于从套接字接收数据的系统调用

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
  • sockfd:一个已连接或已绑定的套接字描述符,指定从哪个套接字接收数据。
  • msg:指向一个 msghdr 结构体的指针,该结构体包含了接收数据的缓冲区信息、可选的目标地址信息
  • flags:可选的标志,用于控制接收操作的行为,例如是否阻塞等待数据、是否只查看数据不移动接收缓冲区指针等。

recvmsg 函数返回接收到的实际字节数,如果连接关闭或发生错误,则返回 -1,并设置 errno 来指出具体错误。通过 recvmsg,可以一次性从多个缓冲区接收数据,并处理附加控制信息,这对于处理复杂网络协议和高级套接字选项非常有用。

sendto recvfrom


sendto 特别适用于无连接的套接字,如UDP套接字。函数原型:

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

参数说明:

  • sockfd:已连接或已绑定的套接字描述符,标识发送数据的套接字。
  • buf:指向要发送的数据缓冲区的指针。
  • len:要发送的数据的字节数。
  • flags:可选的标志,用于控制发送操作的行为,如设置非阻塞模式等。
  • dest_addr:指向 sockaddr 结构体的指针,该结构体包含了目标地址信息(如IP地址和端口号)。
  • addrlendest_addr 指向的地址结构体的长度。

flags选项:
- MSG_CONFIRM:在某些平台上用于确认路径可达性(主要用于多播socket)。
- MSG_DONTROUTE:通常用于诊断,请求数据不要经过路由表,直接发送到本地网络。
- MSG_DONTWAITMSG_NBIO:设置非阻塞模式,如果不能立即发送数据,则返回错误(EAGAIN 或 EWOULDBLOCK),而不是阻塞等待。
这些标志可以通过按位或(|)操作符组合在一起

sendto 函数的主要特点是需要明确指定目标地址,对于无连接的套接字,每条消息都需要指定发送的目标。函数返回值是成功发送的字节数,如果发生错误则返回 -1 并设置 errno。在UDP通信中,sendto 函数常用于发送数据报文至特定的远程主机和端口。


recvfrom 特别适用于无连接的套接字,如UDP套接字。的函数原型:

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

参数说明:

  • sockfd:已绑定的套接字描述符,标识接收数据的套接字。
  • buf:指向用于存储接收到的数据的缓冲区的指针。
  • len:缓冲区的大小,即最多能接收多少字节的数据。
  • flags:可选的标志,用于控制接收操作的行为,如设置非阻塞模式、接收带外数据(OOB)等。
  • src_addr:指向 sockaddr 结构体的指针,用于接收发送数据的源头地址信息。
  • addrlen:指向一个 socklen_t 类型变量的指针,该变量预先存储了 src_addr 结构体的大小,函数完成后会更新为实际存储的地址结构大小。

recvfrom 函数的主要特点是不仅能接收数据,还能获取发送数据的源地址信息。函数返回值是成功接收的字节数,如果发生错误则返回 -1 并设置 errno。在UDP通信中,recvfrom 函数常用于接收数据报文,并得到发送数据的远程主机和端口信息。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值