阅读:1779回复:3
为什么会丢包我用了DDK例子的PACKET来收IP包,可发现会存在丢包现象。 不知是否是程式的毛病。 我用SNIFFER不会丢包。SNIFFER也写一个sniffer.sys. 请哪位高手能有解决不丢包的方法,SOS!!!! |
|
|
沙发#
发布于:2001-12-14 17:11
packet中的收包函数太简单了,没有将接收的缓冲利用好,要想解决不丢包的方法是:组织环形的buffer管理机制,简单来说,缓冲区对收包很关键啊!
你可以参考windump的缓冲管理机制. |
|
|
板凳#
发布于:2001-12-14 18:17
用重叠I/O可以提高些性能,往下提交I/O和接收数据用分开的线程,
当然,packet本身也可以改进。 |
|
|
地板#
发布于:2001-12-14 21:03
用重叠I/O可以提高些性能,往下提交I/O和接收数据用分开的线程, 下面是我98年写的一段代码中的通过packet.sys sniffer 数据包的代码。因为在武汉白云站上曾经有人问过类似的 问题,当时我也曾经贴过。sysinternals版的chyang还曾经 提过一个改进意见,认为event不应该cloaehandle之后又 createevent,而应该复用,我认为他说的很有道理,这样 效率会更高一些。在这里我没有改过来,因为我比较懒。 工作线程应该是for(;;)调用该函数。 这个函数是block的,因此如果要退出程序的时候,有可能 因为这个函数block,无法体面的退出线程,需要用 terminatethread,这显然不够好。解决这个问题的方法 是,增加一个入口参数或者全局变量,hStopEvent,然后 每次waitmultiobject的时候不是等待32个event,而是 33个。当主线程需要退出该线程的时候,只要setevent( hstopevent),waitmultiobject就会返回,然后判断 返回的event,如果是hstopevent,就返回一个ret_stop, (需要把这个函数的返回值改为int,而不是boolean) 然后工作线程的for循环判断返回值就可以return 了。 这种退出方法比较体面干净。 希望以后不要再有人提类似的问题:-)。我有点厌倦。 BOOLEAN RecvPacket( BYTE *pbuf, int *piAdapterNum, PULONG BytesReceived ) { static int iReadAdapterNum=0; BOOLEAN Result; static PACKET Packet[32]; static HANDLE hEvent[32]; DWORD dwByteReceive; HANDLE hEventTemp; int i,j,k; if(g_bFirstCall) // if first call ,let\'s call 32 times readfile first { for(i=0;i<32;i++) { Packet.OverLapped.Offset=0; Packet.OverLapped.OffsetHigh=0; Packet.OverLapped.hEvent=CreateEvent( 0, TRUE, FALSE, NULL ); // manual reset,initial=false hEvent=Packet.OverLapped.hEvent; Packet.Length =1514; // if someone shit send a packet>>1514,what\'s happen? Result=ReadFile( Adapter[iReadAdapterNum].hFile, Packet.Buffer, Packet.Length, &dwByteReceive, &Packet.OverLapped ); Packet.iAdapterNum =iReadAdapterNum; iReadAdapterNum++; iReadAdapterNum=iReadAdapterNum%g_iAdapterNum; // need use a global } g_bFirstCall=false; } i= WaitForMultipleObjects( // which read return? 32, hEvent, false, // wait untill one hevent signal INFINITE // wait ever ); if(i==WAIT_FAILED) return false; for(j=0;j<32;j++) if(Packet[j].OverLapped.hEvent ==hEvent) break; // which read return? k=j; dwByteReceive=0; Result=GetOverlappedResult( Adapter[Packet[k].iAdapterNum].hFile, &Packet[k].OverLapped, &dwByteReceive, false ); if(!Result) { AfxMessageBox(\"!!!\"); return false; } *piAdapterNum=Packet[k].iAdapterNum ; // return value memcpy((void *)pbuf,(void *)Packet[k].Buffer,dwByteReceive); *BytesReceived=dwByteReceive; CloseHandle(Packet[k].OverLapped.hEvent); for(j=i;j<32;i++) hEvent=hEvent[++j]; hEventTemp=CreateEvent(0, TRUE, 0, NULL); if(!hEventTemp) { MessageBox(NULL,\"Can not create event\",NULL,MB_OK); return false; } Packet[k].OverLapped.hEvent=hEventTemp; memset(Packet[k].Buffer,0,1514); Packet[k].Length =1514; hEvent[31]=hEventTemp; // k返回了,就再读K一次 Result=ReadFile( Adapter[Packet[k].iAdapterNum].hFile, Packet[k].Buffer, Packet[k].Length, &dwByteReceive, &Packet[k].OverLapped ); return Result; } |
|
|