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

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

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

前言

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

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

sendmsg函数使用

sendmsg(fd, &mhdr, 0)函数中最重要的就是
msghdr结构体。其定义例如以下:
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的大小有关:

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));

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

最好需要注意的是。要发送以及接收这些控制信息,我们必需要设置套接字选项:
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.net/116643.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 用西尔特编程器解密芯片_配方法解一元二次方程

    用西尔特编程器解密芯片_配方法解一元二次方程z3-solver是由MicrosoftResearch(微软)开发的SMT求解器,它用于检查逻辑表达式的可满足性,可以找到一组约束中的其中一个可行解,缺点是无法找出所有的可行解(对于规划求解问题可以是scipy)。z3-solver可应用于软/硬件的验证与测试、约束求解、混合系统的分析、安全、生物,以及几何求解等问题。Z3主要由C++开发,提供了.NET、C、C++、Java、Python等语言调用接口,下面以python接口展开讲解。……

    2022年10月13日
    3
  • expandablelistview详解[通俗易懂]

    expandablelistview详解[通俗易懂]我在项目中使用到expandablelistview,然后我就在网上找了很多关于expandablelistview的文章,那么这里,将一些对去进行总结一些,并将自己踩过的坑填上。expandablelistview就是类似QQ分组,点击分类,显示其各个详细的分类信息。下面是一些效果图这样是完成了有父标题,和子标题,实现了分组,接下来看看如何布局的。

    2022年6月18日
    30
  • java日期格式化之特殊字符

    如何能够将日期2015-01-29格式化为15W05(表示15年第5周)呢?

    2022年4月7日
    94
  • 软件著作权申请流程_如何申请软件著作权

    软件著作权申请流程_如何申请软件著作权现在越来越多的安卓市场需要软著才能注册或者是才能上线,申请软著势在必行。最简单的方式,简单的准备资料,找第三方代理,不过这样可能花费数百毛爷爷,如果是急需加急,可能是几千。现在简单说一下自己申请的流程:首先贴出中国版权保护中心网站中国版权保护中心:http://apply.ccopyright.com.cn/cpcc/column_list_bqdj.jsp请使用IE浏览器打开一.注册

    2022年9月23日
    4
  • PHP永久激活码2021(最新序列号破解)

    PHP永久激活码2021(最新序列号破解),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月20日
    325
  • Buildroot 用户手册 (中文)

    Buildroot 用户手册 (中文)文章目录I.Gettingstarted1.AboutBuildroot2.Systemrequirements2.1.Mandatorypackages2.2.Optionalpackages3.GettingBuildroot4.Buildrootquickstart4.1configuration4.2build5.CommunityresourcesII.Userguide6.Buildrootconfiguration6.1.Cross-compil

    2022年10月20日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号