前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >利用sendmsg和recvmsg来指定发送接口或者获取接收数据接口

利用sendmsg和recvmsg来指定发送接口或者获取接收数据接口

作者头像
全栈程序员站长
发布于 2022-07-06 12:54:46
发布于 2022-07-06 12:54:46
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是全栈君。

前言

sendmsg和recvmsg函数是一对相对下层的套接字发送、接受函数。

通过这对函数,我们能够设置或者取得数据包的一些额外的控制信息。这些信息中比較经常使用的就是本文要介绍的发送、接受接口信息。通过这对函数,我们能够指定一个数据包发送的时候使用的接口(网卡)或者获得一个接受到数据包的来源接口。

sendmsg函数使用

sendmsg(fd, &mhdr, 0)函数中最重要的就是 msghdr结构体。其定义例如以下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct msghdr {    void         *msg_name; #发送地址    socklen_t    msg_namelen; #前者长度    struct iovec *msg_iov;#发送数据缓冲区的指针    size_t       msg_iovlen;#发送数据长度    void         *msg_control; #控制数据指针    size_t       msg_controllen;#控制数据长度    int          msg_flags;};

在我们发送一个数据包之前。要首先把要发送的数据以及相关控制信息填写到这个结构体中。 这个结构体中包括的是数据以及控制信息的指针。因此在发送之前我们还须要另外为数据和控制信息分配空间。

数据就不用说了,直接char buf[MAX_MSG_SIZE]就可以。难点在于控制信息。

首先要定义一个msghdr 结构体。这个结构体用来存储全部的控制信息和发送的数据包: struct msghdr mhdr; 接着定义控制信息结构体cmsghdr : struct cmsghdr *cmsg; 我们要首先通过CMSG_SPACE 宏计算出控制信息cmsghdr结构体所需的空间大小。接着为控制信息结构体指针分配内存。cmsghdr的大小跟你要填写的控制消息有关。我们这里要填写的是发送接口控制信息,这个控制信息还须要一个结构体struct in6_pktinfo结构体来承载,所以这里cmsghdr的大小则跟in6_pktinfo的大小有关:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct in6_pktinfo pk;//定义接口控制数据结构
pk.ini_index=1;//指定接口(这里的1是接口索引號)
cmsglen =  CMSG_SPACE (sizeof(pk));//计算cmsghdr结构在mhdr中所需的大小
mhdr.msg_control=void *)malloc(cmsglen);//为cmsghdr分配内存,并在mhdr中填写控制信息的指针
mhdr.msg_controllen=cmsglen;
cmsg =  CMSG_FIRSTHDR (&mhdr);//我们利用CMSG_FIRSTHDR找到控制信息在mhdr结构体中的真正地址
//利用CMSG_LEN算出控制信息cmsghdr结构中真正的控制数据的长度
cmsg->cmsg_len = CMSG_LEN(sizeof(*pk));
cmsg->cmsg_level = IPPROTO_IPV6;//填写cmsghdr控制信息结构体
cmsg->cmsg_type = IPV6_PKTINFO;
//CMSG_DATA(cmsg) 能够找到真正的控制信息在cmsghdr结构体中的位置,之后我们就能够利用memcpy把控制结构体的数据复制到cmsg中:
memcpy(CMSG_DATA(cmsg), pk, sizeof(*pk));

以上是发送的过程。接收过程跟发送过程类似。

最好需要注意的是。要发送以及接收这些控制信息,我们必需要设置套接字选项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int val = 1;if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,                       &val, sizeof(val)) < 0)                return -1;        if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVDSTOPTS,                       &val, sizeof(val)) < 0)                return -1;        if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDR,                       &val, sizeof(val)) < 0)                return -1;

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116643.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年1月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • sendmsg函数使用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档