用winpcap抓取icmp数据包后进行处理出现的问题

问题描述:我用winpcap抓取到icmp数据包后,自己构造了一个icmp数据包,ip首部中源地址与目的地址和抓到数据包的源地址与目的地址对调,其他不变,icmp首部中类型填为8(icmp请求),检验和重新计算,其他不变。我在cmd下输入ping www.baidu.com 。
实验期望:可以看到,我抓到了ping下的8个包,4个发送,4个接收,并且我在代码中构造了icmp请求数据包,所以我期望在程序运行中可以源源不断地看到icmp响应,而不只是cmd下的八个包(因为我在抓到数据包后就构造请求报,理论下响应包应该一直会有)。
实际结果:看不到除了8个包以外的其他包。

代码如下:
#include "pcap.h"

/* packet handler 函数原型 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

u_char* ConstructPacket();

u_short cksum(u_short* p,int size);

u_short count = 10;

typedef struct{
BYTE addr1;
BYTE addr2;
BYTE addr3;
BYTE addr4;
}ipaddress;

typedef struct{
u_char ver_hlen;
u_char tos;
u_short totallen;
u_short id;
u_short off;
u_char ttl;
u_char protocal;
u_short crc;
ipaddress srcip;
ipaddress destip;
}ip_header;

typedef struct{
u_char type;
u_char code;
u_short cksum;
u_short id;
u_short seq;
}icmp_header;

pcap_t *adhandle;

int main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
u_int netmask;
char packet_filter[] = "icmp";
struct bpf_program fcode;
    
    /* 获取本机设备列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
    {
        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }
    
    /* 打印列表 */
    for(d=alldevs; d; d=d->next)
    {
        printf("%d. %s", ++i, d->name);
        if (d->description)
            printf(" (%s)\n", d->description);
        else
            printf(" (No description available)\n");
    }
    
    if(i==0)
    {
        printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
        return -1;
    }
    
    printf("Enter the interface number (1-%d):",i);
    scanf("%d", &inum);
    
    if(inum < 1 || inum > i)
    {
        printf("\nInterface number out of range.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }
    
    /* 跳转到选中的适配器 */
    for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
    
    /* 打开设备 */
    if ( (adhandle= pcap_open(d->name,          // 设备名
                              65536,            // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
     PCAP_OPENFLAG_PROMISCUOUS,    // 混杂模式
                              1000,             // 读取超时时间
                              NULL,             // 远程机器验证
                              errbuf            // 错误缓冲池
                              ) ) == NULL)
    {
        fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }

/* 检查数据链路层,为了简单,我们只考虑以太网 */
    if(pcap_datalink(adhandle) != DLT_EN10MB)
    {
        fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }
    
    if(d->addresses != NULL)
        /* 获得接口第一个地址的掩码 */
        netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
    else
        /* 如果接口没有地址,那么我们假设一个C类的掩码 */
        netmask=0xffffff; 


    //编译过滤器
    if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
    {
        fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }
    
    //设置过滤器
    if (pcap_setfilter(adhandle, &fcode)<0)
    {
        fprintf(stderr,"\nError setting the filter.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }
    
    printf("\nlistening on %s...\n", d->description);
    
    /* 释放设备列表 */
    pcap_freealldevs(alldevs);
    
    /* 开始捕获 */
    pcap_loop(adhandle, 0, packet_handler, NULL);
    
    return 0;
}

/* 每次捕获到数据包时,libpcap都会自动调用这个回调函数 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
  u_char* p;

  u_short sum;

  ip_header* ipheader = (ip_header*)(pkt_data+14);

  printf("%d.%d.%d.%d->%d.%d.%d.%d\n",(ipheader->destip).addr1
 ,(ipheader->destip).addr2
 ,(ipheader->destip).addr3
 ,(ipheader->destip).addr4
 ,(ipheader->srcip).addr1
 ,(ipheader->srcip).addr2
 ,(ipheader->srcip).addr3
 ,(ipheader->srcip).addr4);

  int ip_hlen = ((ipheader->ver_hlen)&0xf)*4;
  int totallen = ntohs(ipheader->totallen);
  icmp_header* icmpheader = (icmp_header*)((u_char*)ipheader+ip_hlen);

  p = (u_char*)malloc(totallen);//分配空间
  memcpy(p,(u_char*)ipheader,12);//拷贝ip头部,源地址与目的地址对调
  memcpy(&(((ip_header*)p)->srcip),&(ipheader->destip),4);
  memcpy(&(((ip_header*)p)->destip),&(ipheader->srcip),4);
  ((ip_header*)p)->id = htons(ntohs(ipheader->id)+1);
  ((ip_header*)p)->crc = 0;
   sum = cksum((u_short*)p,ip_hlen/2);
  ((icmp_header*)p)->cksum = sum;
  //以上ip头部拷贝完毕


  u_char* q;
  q = p+ip_hlen;//

  memcpy(&(((icmp_header*)q)->id),&(icmpheader->id),totallen-ip_hlen-4);

  ((icmp_header*)q)->type = 8;
  ((icmp_header*)q)->code = 0;
  ((icmp_header*)q)->cksum = 0;
  ((icmp_header*)q)->seq = htons(ntohs(icmpheader->seq)+1);
  sum = cksum((u_short*)q,(totallen-ip_hlen)/2);
  ((icmp_header*)q)->cksum = sum;

  if(pcap_sendpacket(adhandle, p, totallen /* size */)!=0){//反向发送icmp数据包
    printf("error!\n");
  }

  free(p);
  p = NULL;
    
}

u_short cksum(u_short* p,int size){
int sum = 0;
while(size--){
      sum+=*(p++);
}
sum = (sum>>16)+(sum&0xffff);
sum+=(sum>>16);
    return ~((u_short)sum);
}

回答: 用winpcap抓取icmp数据包后进行处理出现的问题

  1. 用 pcap_sendpacket 发送的包是应该要包含原始的以太网头部的吧,你的包貌似只有 IP 头,没有以太网的头部哦

WinpCap抓取较大UDP数据包问题

  1. Q
    程序中我利用WinpCap抓去另外电脑发送的UDP数据包,UDP数据包大于1514个字节,为什么抓包用pcap_next_ex()抓到的数据包只有一个1514字节的包。其余数据丢掉了,为什么?怎么解决这个问题?
  2. A
    这个应该不难的,你的udp是通过ip分段承载的,ipv4或者ipv6分段包,在链路层有这些ipv4或者ipv6分段包的类型,你查一下wireshark的源码,都有.包括如何把承载upd的ip分段包,拼成完整的upd包,源码都有.

python抓取网页数据错误

  1. Q
    在本地测试就没有任何问题的,只是放到网上就出现问题了.


    在抓取网页的时候,在线版本会丢失http://xxx.xxx.xxxx.net这样的一串链接..而本地就不会,

    在线抓取回来的数据(不是json)
    :



    ;g_img={url:'这个地方本来是应该有url的/az/asdf.jpg',id:'bgDiv',d:'200',cN:'_SS',crN:'bIm',hash:'014',del:'50'};
    sc_bgL();;var g_hot={1:{0:"


    本地抓取的数据:

    ;g_img={url:'http://www.xxxxxxxxxxx.com/az/asdf.jpg',id:'bgDiv',d:'200',cN:'_SS',crN:'bIm',hash:'014',del:'50'};
    sc_bgL();;var g_hot={1:{0:"

    网上原来的环境是:python 2.4
    我自己编译并且把默认的python改成2.7.5[跟本地一样],
    但是里面还有其他的关联python包是不是没更新?

    下面是在线的配置:

    python抓取网页数据错误


    下面是本地的配置:

    python抓取网页数据错误


    抓取网页的代码是[在线没有安装Java,而本地都是有Java运行时环境的]:



    '''
    抓取网页文件内容,保存到内存

    @url 欲抓取文件 ,path+filename
    '''
    def get_file(url):
        try:
            cj=cookielib.LWPCookieJar()
            opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
            urllib2.install_opener(opener)
            req=urllib2.Request(url)
            operate=opener.open(req)
            #这一句是我后面添加的. time.sleep(10)
            data=operate.read()
            return data
        except BaseException, e:
            print e
            return None


    等大神解决,谢谢了

    对了在线的系统环境是centos5.9(原来的版本是2.4,后来改成2.7.5),本地的是fedora20和windows7(本地都是(2.7.5版本)能抓取到url,只是在线的抓不到)
  2. A
    是很奇怪,抓下包看看吧,目标网站是不是有bug.....那url连域名都没有应该打不开吧

IBasicVideo无法抓取视频数据

  1. Q
    IBasicVideo无法抓取视频数据

    以上是利用IBasicVideo抓取视频流数据并保存BMP格式图片的代码,但是以上代码有个很奇怪的问题,就是正常运行程序时GetCurrentImage可以抓到一帧的大小却抓不到图像数据,可是在抓取图像数据的GetCurrentImage处设置断点调试时却可以抓到图像数据并成功保存BMP图片。路过的大哥请帮忙看看。谢谢!
  2. A
    这个GetCurrentImage是不是异步函数?
    在非调试状态下抓不到图像,是返回值hr的问题还是buffer是空的?

请教高手bcb定时抓取网页数据并处理的问题?

  1. Q
    请教高手bcb定时抓取网页数据并处理的问题?
    (最少每分钟一次)
    1.用NMHTTP还是IdHTTP?或者其它更好的方式?
     用NMHTTP不定期出错?一分钟内多次抓取出错,好象是已经连接的问题,能不能先断开再抓取?
    //---------------------------------------------------------------------------
    AnsiString __fastcall get_http_html(char* htt)
    {
        AnsiString ss;
        try{
        //            能不能先断开再抓取?
            Form1->NMHTTP1->TimeOut = 30000;
            Form1->NMHTTP1->InputFileMode = false;
            Form1->NMHTTP1->OutputFileMode = false;
            Form1->NMHTTP1->ReportLevel = Status_Basic;
            if(Form1->NMHTTP1->Connected==false)
            Form1->NMHTTP1->Get(htt);
            ss=Form1->NMHTTP1->Body;
        }
        catch(...)
        {
        }
        return ss;
    }
    2.定时器Timer工作时程序界面停止响应,如果用线程,程序框架该怎样写?

    //---------------------------------------------------------------------------
    void __fastcall TForm1::TimerworkTimer(TObject *Sender)
    {
        get_min_http((get_http_html2(all_http.c_str())).c_str());  //抓取
        view_min(); //计算并显示
    }
  2. A
    Form1->IdHTTP1->Disconnect();
    这样即可、

关于抓取网页数据!!!

  1. Q
    昨天我去面试一家公司,那老板说你回去用jsp做一个项目,好了你就可以上班了.....

    要求是可以从指定网页中抓取需要的数据。
    例如:我在baidu上搜索“电视”,那么我要从他返回的页面上抽取他的关键字!(注意:只是抽取客户端显示网页的数据)

    当着为老板提到这个题目时,我就想到了“网络爬虫”。
    我是这样想的:1.做一个jsp页面,向其中输入一条信息,然后由它转发到baidu。
                  2.然后接收、下载返回的页面。
                  3.把返回的html网页当成一个xml文件那样逐条逐条的分析、过滤。
                  4.对过滤好的数据进行整理后,抽取其中我需要的部分,然后再返回到自己的jsp页面进行显示!

    以上就是我的思路,请各位大神们指点指点,还有什么需要注意和改进的。
    对于接收过来的页面,如何进行分析,过滤,我的思绪不是很清新,欢迎大家向我提各种建议,和提醒我那些需要注意的!
  2. A
    不知道,楼主解决了没有,建议你可以去看一下nutch,这是一个从  抓取网页到页面分析,到建索,到查询,都完整实现的搜索引擎,是开源的
    引用 12 楼 luojihaidao 的回复:
    引用 5 楼 java2000_net 的回复:
    1 抓取
    2 正则匹配

    OVER


    那一个效率好呢???

    楼主的思路,其实就 这两步的具体解释,1,抓取,就是楼主说的 :“网络爬虫”。
    我是这样想的:1.做一个jsp页面,向其中输入一条信息,然后由它转发到baidu。
                  2.然后接收、下载返回的页面。
    2,正则匹配就是指楼主提到的:      3.把返回的html网页当成一个xml文件那样逐条逐条的分析、过滤。
                  4.对过滤好的数据进行整理后,抽取其中我需要的部分
    然后再返回到自己的jsp页面进行显示!这一步,其实就是nutch中的查询了
    以上的东西,在nutch中都已经实现了,可以参考下 

垂直搜索,用heritrix抓取网页数据时,数据过滤不彻底

  1. Q
    我在做垂直搜索,数据来源是太平电脑网,我关心的是里面的手机信息,我定制heritrix的FrontierScheduler类,代码如下:

    package my.processor;

    import java.util.logging.Logger;

    import org.archive.crawler.datamodel.CandidateURI;
    import org.archive.crawler.postprocessor.FrontierScheduler;

    public class FrontierSchedulerForPconlineMobile extends FrontierScheduler {
    private static Logger LOGGER = Logger.getLogger(FrontierSchedulerForPconlineMobile.class.getName());

    public FrontierSchedulerForPconlineMobile(String name) {
    super(name);
    }

    protected void schedule(CandidateURI caUri){
    String url=caUri.toString();
    try{
    if(url.indexOf("product.pconline.com.cn/mobile/")!=-1
    || url.indexOf("product.pconline.com.cn/pdlib/")!=-1
    || url.indexOf("img.pconline.com.cn/images/product/")!=-1
    || url.endsWith(".jpg")
    || url.indexOf("robots.txt")!=-1
    || url.indexOf("dns:")!=-1){
    getController().getFrontier().schedule(caUri);
    }else{
    return ;
    }
    }catch(Exception e){
    e.printStackTrace();
    }finally{
    }
    }
    }

    然后设置好后开始抓取。抓出来的数据是这样的:

    请帮我看看,这数据抓的正常吗?我看了里面的有些数据,感觉垃圾数据挺多的。我还刚开始弄搜索引擎,请多多指教!!
  2. A
    顶顶~~~~~~

快速抓取网页数据入库

  1. Q
    抓取了网页的html代码保存在一个文本文件里,如何将其table表格里的数据快速定位并入库,高手降临指教!!!
    ---------------------- 以下就是抓取存在文件里的内容
    <html>
    <head>
    <title>****</title>
    <link href="layout2.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
    <div id="container">
      <div id="header"></br><h1>5806系统后台</h1></div>
    <div id="menu">
    <ul >  
    <li><a href="">对账结果</a></li>
    <li><a href="">订购查询</a></li>
      
    <li><a href="">退出登录</a></li>
    </ul>
    </div>

      <div id="mainContent">
        <div id="sidebar">
       
        </div>
        <div id="content">
            <table width="90%">
        <tr><td></br><h1>订购查询</h1></td></tr>
        <tr><td>
        <table width="90%" border="0" bordercolor="#FFFFFF" cellspacing="0" cellpadding="0">

                 共分1页显示,当前是
                     1页.
                     <form id='form6' name='form6' method='post' action=''>  <label>跳转到第<select name='pageid' id='pageid'>
    <option value='1'>1</option>
      </select>页</label>  <input type='submit' value='提交' /></form>

    </hr>
    <tr>
    <td>名称</td>
    <td>时间</td>
    <td>代码</td>
    <td>代码</td>
    <td>总数</td>
    <td>总金额</td>
    <td>小计</td>
    </tr>
    <tr class="trlist">
    <td>104&nbsp;&nbsp;</td>
    <td>2012-10-02 00:00:00.0&nbsp;&nbsp;</td>
    <td>022&nbsp;&nbsp;</td>
    <td>103&nbsp;&nbsp;</td>
    <td>1&nbsp;&nbsp;</td>
    <td>2&nbsp;&nbsp;</td>
    <td>&nbsp;&nbsp;</td>
    </tr>
    <tr class="trlist">
    <td>&nbsp;&nbsp;</td>
    <td>&nbsp;&nbsp;</td>
    <td>&nbsp;&nbsp;</td>
    <td>&nbsp;&nbsp;</td>
    <td>&nbsp;&nbsp;</td>
    <td>&nbsp;&nbsp;</td>
    <td>2&nbsp;&nbsp;</td>
    </tr>
    </table>
    </td></tr></table>
    </div>
      </div>
      <div id="footer">
    <p>&nbsp;</p>
    CopyRight 2011-2015</p>

      </div>
    </div>
    </body>
    </html>
  2. A
    考虑使用下jsoup吧 类似于css/jquery语法

求助用VBA抓取网页数据(求版主帮助~~)

  1. Q
    本人初学VBA,需要在http://www.sse.com.cn/disclosure/diclosure/etf/index.shtml?type=8&etfClass=2这个网站上抓取表格里面的数据,但是它的源文件中显示不出表格的数据,这样应该怎么读取呢?很紧急,望版主和各位大神帮助。。
  2. A
    Excel Vba:


    Sub 成份股信息内容()
        On Error Resume Next
        Cells.Clear
        Cells.NumberFormatLocal = "@"
        Set ms = CreateObject("MSScriptControl.ScriptControl")
        ms.Language = "javascript"
        ar = Split("instrumentId,instrumentName,quantity,substituteFlag,premiumRate,cashAmount", ",")
        With CreateObject("WinHttp.WinHttpRequest.5.1")
            .Open "GET", "http://query.sse.com.cn/infodisplay/queryConstituentStockInfo.do?jsonCallBack=a&isPagination=false&type=8&market=&etfClass=2&_=" & ms.Eval("new Date().getTime()"), False
            .SetRequestHeader "Referer", "http://www.sse.com.cn/disclosure/diclosure/etf/index.shtml?type=8&etfClass=2"
            .SetRequestHeader "Connection", "Keep-Alive"
            .Send
            ms.AddCode Replace(Replace(.responseText, "(", "="), ")", "")
            yema = ms.Eval("a.result.length")
            For i = 0 To yema
                For j = 0 To 5
                    Cells(i + 1, j + 1) = ms.Eval("a.result[" & i & "]." & ar(j))
                Next
            Next
        End With
    End Sub

急救啊 抓取网页数据保存到本地数据库 有1万多页啊

  1. Q
    http://app1.sfda.gov.cn/datasearch/face3/base.jsp?tableId=25&tableName=TABLE25&title=国产药品&bcId=124356560303886909015737447882

    那位大侠能帮帮小弟 抓取这个网站上的药品信息并保存到本地数据库 最好能进入药品的下级目录 取得更多的数据内容  共1万多页  是在抱歉 图片上传不了
  2. A

    Clear
    nTime = Seconds()
    nDelayTime = 2  && 延时时间,如果你的网速慢,秒数酌情放大
    Public oie, objTable, nPages
    nStartPage = 1  && 起始页
    nEndPage = 10  && 结束页

    Create Cursor 国产药品 (序号 N (6), 产品名称 C(40), 批准文号 C(20), 生产单位 C(40), 药品本位码 C(70) )
    oIE = Createobject("internetexplorer.application")
    oIE.Visible = .F.
    oIE.Navigate("http://app1.sfda.gov.cn/datasearch/face3/base.jsp?tableId=25&tableName=TABLE25&title=国产药品&bcId=124356560303886909015737447882")
    =WaittingFor()

    For I = nStartPage To nEndPage
        Wait Window "正在提取数据,预计耗时(秒):"  + Alltrim( Str((nEndPage - nStartPage + 1) * nDelayTime * 1.1 ) ) + Chr(13) + ;
            "现在正在提取:" + Alltrim( Str(I) ) + " of " + Alltrim( Str(nEndPage) ) + " 页" Nowait
        nPages = "javascript:devPage(" + Alltrim(Str(I)) + ")"
        oIE.Navigate(nPages)
        =WaittingFor()
        Do GetDates
    Endfor

    Wait Window "耗时(秒) : " + Alltrim(Str(Seconds() - nTime)) Timeout 3
    oIE.Quit()
    Go Top
    Browse Last

    Return


    Function WaittingFor  && 延时
        tStartSecond = Seconds()
        Do While oIE.Busy=.T. Or oIE.ReadyState#4
            If Seconds() - tStartSecond > nDelayTime
                Exit
            Endif
        Enddo


    Procedure GetDates  && 提取该页数据
        objCollection = oIE.Document.getElementsByTagName("Table").[156]
        objTable = objCollection
        For Each objRow In objTable.Rows
            If Empty(objRow.cells(0).innertext)
            Else
                Insert Into 国产药品 Values (;
                    VAL(Strextract(objRow.cells(0).innertext, [], [.])), ;
                    Strextract(objRow.cells(0).innertext, [.], [ (国药准字]), ;
                    Strextract(objRow.cells(0).innertext, [ (国药准字], [ ]), ;
                    Strextract(objRow.cells(0).innertext, [ ], [ ], 2), ;
                    Strextract(objRow.cells(0).innertext, [ ], [)], 3) )
            Endif
        Next