???????

最近自己因為實際需要,用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?2。6,內存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,?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.????? 當已經發現包之后還會等多一些的包一起返回,等待時間就是read timeout.明白了,我把read timeout設為1以后時延降到了<10ms.
?????其中還需要提醒的是用Ethereal等一些抓包工具看到收包到轉發時延很大時就以為是pcap_next_ex()和pcap_sendpacket()函數之間的處理造成了時延.這里容易給我們產生一個假相.以為網卡收到包的時刻就是轉發程序就要開始處理.實際上pcap_next_ex()還在等待更多的包一起返回.
?????所以事發的原因離事發現場比較遠.在pcap_open()那.程序就就是怎么千絲萬縷的關聯著.
???? 大家一定要多懷疑自己,別去怪罪工具.winpcap很無辜的.嘻嘻!!
肚子餓了去吃飯
!!
?????????????????????????????????????????????????????????????????????-----saga.constantine