???????

最近自己因為實際需要,用winpcap開發(fā)一個程序里面有需要轉(zhuǎn)發(fā)包.自己就寫了一個,發(fā)現(xiàn)轉(zhuǎn)發(fā)時延>500ms.也確實把自己嚇到了.便把轉(zhuǎn)發(fā)的那段代碼開始精減,大致如下
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()發(fā)包.

怎么想都不會有那么大的時延.很不解就搜索了下關(guān)于pcap_sendpacket()發(fā)包效能的網(wǎng)頁,其中有一個
http://community.csdn.net/Expert/TopicView3.asp?id=4153633來里面有人說
我用winpcap做個一個初步的試驗,我得機器是奔4?2。6,內(nèi)存512,我一個線程接包,一個線程收包,用動態(tài)連表做緩存,一秒鐘轉(zhuǎn)發(fā)1-2個包沒有多大問題,要是再多了,就會又丟包,轉(zhuǎn)發(fā)上千萬包要丟幾百個。還有人說
winpcap的sendpacket超級慢,而且延遲很大。

我試圖實現(xiàn)一個bridge,即一個端口進入的包不經(jīng)修改從一個端口出,反之亦然。結(jié)果ping的結(jié)果顯示延遲為數(shù)百毫秒級別,個別時候甚至到了1秒。運行其它應(yīng)用更是不可忍受。

我想使用sendQuene,結(jié)果sendQuene的具體用法只見過預(yù)先準備好所有的包然后整體發(fā)送的,沒見過隨著包來隨著發(fā)送的例子。或許對于我的bridge,winpcap是一個錯誤的選擇?又或者大家有什么新鮮的思路?愿意聽大家說說。???? ?? 使我也開始懷疑pcap_sendpacket()了.難道真實pcap_sendpacket()效率底.但是我還是不相信.堂堂winpcap怎么可能怎么慢.使我發(fā)現(xiàn)破綻的使貼子里最后一的人的說法:
我也寫了個類似的程序,延時穩(wěn)定在20ms左右,帶寬可以達到10M
我發(fā)現(xiàn)一個有趣的事情,即我在運行brigde的服務(wù)器上,運行一個fluke的抓包工具,居然發(fā)現(xiàn)運行后,通過bridge后的時延居然只有1ms左右了,停止抓包工具后,延時又回到20ms左右,試了多次情況都一樣

打開網(wǎng)卡的句柄是按下面的參數(shù)執(zhí)行的
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?
);?
對數(shù)據(jù)報的捕獲是用pcap_loop函數(shù),我試過將pcap_open的read?timeout參數(shù)設(shè)置為-1,即讀取立即返回,但這樣對系統(tǒng)資源占用太大,cpu利用率增加到100%,此時bridge的延時就很不穩(wěn)定了,從1ms到1s都有。?????? 他在里面特意提到了pcap_open()的read timeout參數(shù),我回想起我的設(shè)的1000ms,也就是一秒.嫌疑很大.(注:我用的是pcap_open_live())
pcap_open_live(d->name,?1000,?1,?1000,?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.????? 當已經(jīng)發(fā)現(xiàn)包之后還會等多一些的包一起返回,等待時間就是read timeout.明白了,我把read timeout設(shè)為1以后時延降到了<10ms.
?????其中還需要提醒的是用Ethereal等一些抓包工具看到收包到轉(zhuǎn)發(fā)時延很大時就以為是pcap_next_ex()和pcap_sendpacket()函數(shù)之間的處理造成了時延.這里容易給我們產(chǎn)生一個假相.以為網(wǎng)卡收到包的時刻就是轉(zhuǎn)發(fā)程序就要開始處理.實際上pcap_next_ex()還在等待更多的包一起返回.
?????所以事發(fā)的原因離事發(fā)現(xiàn)場比較遠.在pcap_open()那.程序就就是怎么千絲萬縷的關(guān)聯(lián)著.
???? 大家一定要多懷疑自己,別去怪罪工具.winpcap很無辜的.嘻嘻!!
肚子餓了去吃飯
!!
?????????????????????????????????????????????????????????????????????-----saga.constantine