利用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;

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

时间: 2024-08-08 05:35:44

利用sendmsg和recvmsg来指定发送接口或者获取接收数据接口的相关文章

疾病API接口免费开放-APP数据接口

医疗中心 (medical.yi18.net)是医药吧网(www.yi18.net)旗下的医疗信息网. 专门提供疾病信息,专门的疾病数据库中心. 现在医疗中心网 中有8千左右的疾病数据信息,同时每天有5个左右的数据更新. 虽然食品总数不多,但我们会不断的更新域维护. API不仅提供APP调用,同时也可以支持网站调用.免费开放,永久支持! API文档地址:doc.yi18.net/diseaseapidoc 疾病API接口的开放,主要提供快速生存APP应用,为APP应用提供免费的数据接口. 比如:

猫眼电影App抓包获取评论数据接口

?之前在CSDN程序人生公众号上看到了这篇文章<邪不压正>评分持续走低,上万条网友评论揭秘,是救救姜文还是救救观众?,文中提到了通过抓包猫眼App发现了评论的数据接口:http://m.maoyan.com/mmdb/comments/movie/248566.json?_v_=yes&offset=1,其中248566属于电影的专属id,offset代表页数,但并未提及如何在猫眼App抓包.经过笔者的摸索,在尝试Charles等各种抓包工具后,踩了无数的坑之后,最终使用Fiddler

ASP.NET API(MVC) 对APP接口(Json格式)接收数据与返回数据的统一管理

话不多说,直接进入主题. 需求:基于Http请求接收Json格式数据,返回Json格式的数据. 整理:对接收的数据与返回数据进行统一的封装整理,方便处理接收与返回数据,并对数据进行验证,通过C#的特性对token进行验证,并通过时间戳的方式统一处理接收与返回的时间格式. 请求Json格式: { "Cmd": "login", "Token": "", "PageNo": 0, "OnePageNu

java URL实现调用其他系统发送报文并获取返回数据

模拟本系统通过Url方式发送报文到目标服务器,并获取返回数据:(实现类) 1 import java.io.BufferedOutputStream; 2 import java.io.BufferedReader; 3 import java.io.InputStream; 4 import java.io.InputStreamReader; 5 import java.io.OutputStream; 6 import java.io.OutputStreamWriter; 7 impor

Android利用异步任务AsyncTask发送post请求获取json数据

AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程. 使用的优点: l  简单,快捷 l  过程可控 使用的缺点: l  在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来. 2 )Handler异步实现的原理和适用的优缺点 AsyncTask介绍 Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理.

java接收数据接口

1.数据接收接口: 这个可以考虑最简单的Servlet方法,而且效率较高: import java.io.PrintWriter;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Enumeration; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.ht

ios开发之发送UDP广播并接收数据

用了asyncUdpSocket, 服务端在接收到广播后,就会做出回应,然后就可以开始通讯了. - (void)init{ AsyncUdpSocket *socket=[[AsyncUdpSocketalloc]initWithDelegate:self]; [socketlocalPort:16747]; NSTimeInterval timeout=5000; NSString *[email protected]"quick_stat"; NSData *data=[NSDat

根据URL接口地址获取JSON数据

//根据URL回发地址获取用户json数据        private string GetJsonByUrl(string url)        {            System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);            System.Net.HttpWebResponse response = (System.Ne

react jquery方式获取api数据接口

import React, { Component } from 'react'; import Record from './Record'; import { getJSON } from 'jquery'; class Records extends Component { constructor() { super(); this.state = { error: null, isLoaded: false, records: [] }; } componentDidMount() {