saga's blog

突出重点,系统全面,不留死角

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  33 Posts :: 2 Stories :: 185 Comments :: 0 Trackbacks

公告

QQ:34O859O5

常用链接

留言簿(15)

搜索

  •  

积分与排名

  • 积分 - 209529
  • 排名 - 121

最新评论

阅读排行榜

评论排行榜

        最近自己因为实际需要,用winpcap开发一个程序里面有需要转发包.自己就写了一个,发现转发时延>500ms.也确实把自己吓到了.便把转发的那段代码开始精减,大致如下
while((j=pcap_next_ex(slecadopt,&pkt_header,(const u_char**)&pkt_data))>=0)
{   
     
if(j==0)
     
{
     
continue;
     }

     
if(*(unsigned short *)(pkt_data+12)==htons(ETH_IP)&&(!(memcmp(pkt_data+6,myip->mac,6)==0))&&*(unsigned long *)(pkt_data+30)!=myip->ip&&(!(memcmp(pkt_data,bcast,6)==0)))
     

     
for(z=Pipmachead;z!=NULL;z=z->next)
     
{
         
if(*(unsigned long *)(pkt_data+30)==z->ip)
             
{
                        memcpy(cmac
->mac,z->mac,6);
                        memcpy(cmac
->mac+6,myip->mac,6);
                        memcpy(sendbuf,pkt_data,pkt_header
->caplen);
                        memcpy(sendbuf,cmac,
12);
                       pcap_sendpacket(slecadopt,sendbuf,pkt_header
->caplen);      
         }
 
         
continue;
     }

     }

}
        过程很简单,pcap_next_ex()收包,在做判断处理,然后用pcap_sendpacket()发包.怎么想都不会有那么大的时延.很不解就搜索了下关于pcap_sendpacket()发包效能的网页,其中有一个http://community.csdn.net/Expert/TopicView3.asp?id=4153633来里面有人说
我用winpcap做个一个初步的试验,我得机器是奔4 26,内存512,我一个线程接包,一个线程收包,用动态连表做缓存,一秒钟转发1-2个包没有多大问题,要是再多了,就会又丢包,转发上千万包要丢几百个。
还有人说
winpcap的sendpacket超级慢,而且延迟很大。

我试图实现一个bridge,即一个端口进入的包不经修改从一个端口出,反之亦然。结果ping的结果显示延迟为数百毫秒级别,个别时候甚至到了1秒。运行其它应用更是不可忍受。

我想使用sendQuene,结果sendQuene的具体用法只见过预先准备好所有的包然后整体发送的,没见过随着包来随着发送的例子。或许对于我的bridge,winpcap是一个错误的选择?又或者大家有什么新鲜的思路?愿意听大家说说。
        使我也开始怀疑pcap_sendpacket()了.难道真实pcap_sendpacket()效率底.但是我还是不相信.堂堂winpcap怎么可能怎么慢.使我发现破绽的使贴子里最后一的人的说法:
我也写了个类似的程序,延时稳定在20ms左右,带宽可以达到10M
我发现一个有趣的事情,即我在运行brigde的服务器上,运行一个fluke的抓包工具,居然发现运行后,通过bridge后的时延居然只有1ms左右了,停止抓包工具后,延时又回到20ms左右,试了多次情况都一样

打开网卡的句柄是按下面的参数执行的
pcap_open(d
->name, // name of the device 
65536// portion of the packet to capture.
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode 
1// read timeout 
NULL, // remote authentication 
errbuf // error buffer 
); 
对数据报的捕获是用pcap_loop函数,我试过将pcap_open的read timeout参数设置为
-1,即读取立即返回,但这样对系统资源占用太大,cpu利用率增加到100%,此时bridge的延时就很不稳定了,从1ms到1s都有。
       他在里面特意提到了pcap_open()的read timeout参数,我回想起我的设的1000ms,也就是一秒.嫌疑很大.(注:我用的是pcap_open_live())
pcap_open_live(d->name, 100011000, error)
然后就去查Winpcap的官方资料http://www.winpcap.org/docs/docs31/html/group__wpcapfunc.html
里面说的很清楚:
to_ms specifies the read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it wait for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. 

     当已经发现包之后还会等多一些的包一起返回,等待时间就是read timeout.明白了,我把read timeout设为1以后时延降到了<10ms.

     其中还需要提醒的是用Ethereal等一些抓包工具看到收包到转发时延很大时就以为是pcap_next_ex()和pcap_sendpacket()函数之间的处理造成了时延.这里容易给我们产生一个假相.以为网卡收到包的时刻就是转发程序就要开始处理.实际上pcap_next_ex()还在等待更多的包一起返回.
     所以事发的原因离事发现场比较远.在pcap_open()那.程序就就是怎么千丝万缕的关联着.
     大家一定要多怀疑自己,别去怪罪工具.winpcap很无辜的.嘻嘻!!肚子饿了去吃饭!!

                                                                     -----saga.constantine

posted on 2006-04-16 17:13 saga.constantine 阅读(11616) 评论(12)  编辑 收藏 引用 所属分类: Winpcap

Feedback

# re: [原创]用Winpcap函数转发包需要留心的一点 2006-04-17 08:43 任我行
学习中,我要做的是先收包,然后修改包头,再发送包。
还不知道WinPcap能否做到。
我也看了看这个库。没有你研究的那么深入。
我在这里关注你的进展。
  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2006-04-17 08:53 saga.constantine
@任我行
谢谢关注,我也是在学习,对winpcap了解也不深,一般能达到目的就不在研究了,呵呵.收包,改包头,发送就是我上面给出代码的功能.winpcap擅长的就是这方面把.发送你任意改过的包!  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2006-04-17 09:26 任我行
@saga.constantine
好,其实我想做一个proxy,先收,再改,然后发。
有方向就好办了。到时搞到问题再来向你要答案。
  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2006-04-28 16:52 任我行
刚才练习了以下WinPcap,还是不太会用。
能否发些例子来学习学习。
先来一个发包程序,例如:自己组装一些IP包,然后发出去,
在来一个收包程序,接收上面发过来的IP包,并提取其中相关的数据。

  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2006-04-28 19:22 saga.constantine
@任我行
你看我的另一篇post里面的arp欺骗 代码拉.里面发包收包都有......
for(k=0;k<6;k++)
{
eth.eh_dst[k]=0xff;
eth.eh_src[k]=0x0f;
arp.arp_sha[k]=0x0f;
arp.arp_tha[k]=0x00;
}
eth.eh_type=htons(ETH_ARP);
arp.arp_hdr=htons(ARP_HARDWARE);
arp.arp_pro=htons(ETH_IP);
arp.arp_hln=6;
arp.arp_pln=4;
arp.arp_opt=htons(ARP_REQUEST);
arp.arp_tpa=myip->ip;
arp.arp_spa=inet_addr("127.0.0.2"); //随便设的请求方ip

memset(sendbuf,0,sizeof(sendbuf));
memcpy(sendbuf,&eth,sizeof(eth));
memcpy(sendbuf+sizeof(eth),&arp,sizeof(arp));

if(pcap_sendpacket(slecadopt,sendbuf,42)==0)
{
printf("PacketSend succeed\n\n");
}
else
{
printf("PacketSendPacket in getmine Error: %d\n",GetLastError());
return 0;
}
就可以发一个简单的arp请求包!!

  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2008-06-27 08:54 狼唇之吻
LZ你好,我使用wpcap编程时,使用int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)获取网卡列表,在windows xp下没有发生任何问题,但是在windows 2000里面发现有很大部分获取不到正在使用的网卡。

而是获取到的只有一个dialup and vpn capture

请问这个大概什么原因。
我测试了100台左右的2000系统,有将近一半不行。200多台XP一点问题都没有  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2008-07-03 09:45 saga
抱歉 不知道@狼唇之吻
  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2008-07-03 19:19 SG
转发包出去的包不会又被pcap_next_ex捕获回来吗??
如果 我只想捕获接收到的包,不想捕获网卡发出去的包有没办法哪?
前提不提取数据判断方向,我也看了点资料资料上都写着
if(pcap_next_ex == 1)我实验过好象不太有用我所有发出去的包都被忠实的捕获回来,很郁闷,当然我不是仅仅把捕获的到的包修改下再发出发 我发出的是另外一个包 大概结构就象第一个程序快 郁闷啊  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2009-01-13 15:42 complexs.net
可以使用Winpcap提供的过滤函数,来过滤不需要的包.
这样可以提高网络堆栈的性能,提高发包速度.

关于Winpcap丢包的现象,是因为发包的速度慢造成的,应该尽可能的降低发包速度.

我使用Winpcap开发,传送10G大的文件,速度平均在8M左右.

理想速度应该尽量接近10M,功力不够~!  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2009-12-25 09:51 jjl
你试试在PCAP_OPEN()把打开标志设置为混杂模式和不捕获本地包模式,也就是数字9.  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2012-06-03 18:44 吴同学
LZ十分谢谢你啊!!!!
我的程序ARP做的监控软件,就是觉得好慢!!被你这样一说改了那个时间,真的快了好多啊!!!!!
十分谢谢!!
虽然是好多年前的.  回复  更多评论
  

# re: [原创]用Winpcap函数转发包需要留心的一点 2013-12-17 22:56 11
你做出来了吗?@SG
  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理