这段时间很多朋友都写邮件问我如何得到拨号上网时的网络速度,下面的代码是在我的软件Dial 
    Monitor中节选出来的相关程序片。 
    
    H文件:rasSpdM.h 
    
    #ifndef __RASSPDMON_H_
    #define __RASSPDMON_H_
    
    void InitSpeedMonitor(void);
    void ClearSpeedMonitor(void);
    void GetRASSpeed(DWORD* pTPS,DWORD* pRPS,DWORD* pTT,DWORD* pRT);
    ////参数:每秒发送,每秒接收,总发送,总接受
    
    
    #endif
    
    
    CPP文件rasSpdM.Cpp
    
    #inClude "stdafx.h"
    #inClude "rasSpdM.h"
    
    
    #inClude 
    
    #define TOTALBYTES 4096
    #define BYTEINCREMENT 1024
    
    LPSTR lpNameStrings=NULL;
    LPSTR *lpNamesArray=NULL;
    BOOL glo_fFromDynReg=TRUE;
    
    /*
    在9x下通过dyn_data注册表得到速度
    */
    DWORD GetTotalReCv(void)
    {
    HKEY hKey;
    DWORD dwValue=(DWORD)-1;
    if(0==RegOpenKey(HKEY_DYN_DATA,"PerfStatsStatData", &hKey))
    {
    DWORD dwType,dwLen=sizeof(DWORD);
    RegQueryValueEx(hKey,"Dial-Up AdapterTotalBytesReCvd",NULL,&dwType,(BYTE*)&dwValue, 
    &dwLen);
    RegCloseKey(hKey);
    }
    return dwValue;
    }
    DWORD GetTotalXmit(void)
    {
    HKEY hKey;
    DWORD dwValue=(DWORD)-1;
    if(0==RegOpenKey(HKEY_DYN_DATA,"PerfStatsStatData",&hKey))
    {
    DWORD dwType,dwLen=sizeof(DWORD);
    RegQueryValueEx(hKey,"Dial-Up AdapterTotalBytesXmit",NULL,&dwType,(BYTE*)&dwValue,&dwLen);
    RegCloseKey(hKey);
    }
    return dwValue;
    }
    DWORD GetPerSeCondReCv(void)
    {
    HKEY hKey;
    DWORD dwValue=(DWORD)-1;
    if(0==RegOpenKey(HKEY_DYN_DATA,"PerfStatsStatData",&hKey))
    {
    DWORD dwType,dwLen=sizeof(DWORD);
    RegQueryValueEx(hKey,"Dial-Up AdapterBytesReCvd",NULL,&dwType,(BYTE*)&dwValue,&dwLen);
    RegCloseKey(hKey);
    }
    return dwValue;
    }
    DWORD GetPerSeCondXmit(void)
    {
    HKEY hKey;
    DWORD dwValue=(DWORD)-1;
    if(0==RegOpenKey(HKEY_DYN_DATA,"PerfStatsStatData",&hKey))
    {
    DWORD dwType,dwLen=sizeof(DWORD);
    RegQueryValueEx(hKey,"Dial-Up AdapterBytesXmit",NULL,&dwType,(BYTE*)&dwValue,&dwLen);
    RegCloseKey(hKey);
    }
    return dwValue;
    }
    
    /****************************************************
    在NT下通过per Data得到
    *****************************************************/
    
    PPERF_OBJECT_TYPE FirstObjeCt( PPERF_DATA_BLOCK PerfData )
    {
    return( (PPERF_OBJECT_TYPE)((PBYTE)PerfData + 
    PerfData->HeaderLength) );
    }
    
    PPERF_OBJECT_TYPE NextObjeCt( PPERF_OBJECT_TYPE PerfObj )
    {
    return( (PPERF_OBJECT_TYPE)((PBYTE)PerfObj + 
    PerfObj->TotalByteLength) );
    }
    
    PPERF_INSTANCE_DEFINITION FirstInstanCe( PPERF_OBJECT_TYPE PerfObj )
    {
    return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj + 
    PerfObj->DefinitionLength) );
    }
    
    PPERF_INSTANCE_DEFINITION NextInstanCe( 
    PPERF_INSTANCE_DEFINITION PerfInst )
    {
    PPERF_COUNTER_BLOCK PerfCntrBlk;
    
    PerfCntrBlk = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst + 
    PerfInst->ByteLength);
    
    return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfCntrBlk + 
    PerfCntrBlk->ByteLength) );
    }
    
    PPERF_COUNTER_DEFINITION FirstCounter( PPERF_OBJECT_TYPE PerfObj )
    {
    return( (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj + 
    PerfObj->HeaderLength) );
    }
    
    PPERF_COUNTER_DEFINITION NextCounter( 
    PPERF_COUNTER_DEFINITION PerfCntr )
    {
    return( (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr + 
    PerfCntr->ByteLength) );
    }
    
    /*****************************************************
    * *
    * Load the Counter and objeCt names from the registry to the *
    * global variable lpNamesArray. *
    * *
    *******************************************************/
    
    void GetNameStrings( )
    {
    HKEY hKeyPerflib; // handle to registry key
    HKEY hKeyPerflib009; // handle to registry key
    DWORD dwMaxValueLen; // maximum size of key values
    DWORD dwBuffer; // bytes to alloCate for buffers
    DWORD dwBufferSize; // size of dwBuffer
    LPSTR lpCurrentString; // pointer for enumerating data strings
    DWORD dwCounter; // Current Counter index
    
    // Get the number of Counter items.
    
    RegOpenKeyEx( HKEY_LOCAL_MACHINE,
    "SOFTWAREMiCrosoftWindows NTCurrentVersionPerflib",
    0,
    KEY_READ,
    &hKeyPerflib);
    
    dwBufferSize = sizeof(dwBuffer);
    
    RegQueryValueEx( hKeyPerflib,
    "Last Counter",
    NULL,
    NULL,
    (LPBYTE) &dwBuffer,
    &dwBufferSize );
    
    RegCloseKey( hKeyPerflib );
    
    // AlloCate memory for the names array.
    
    lpNamesArray = (Char**)malloC( (dwBuffer+1) * sizeof(LPSTR) );
    // Open key Containing Counter and objeCt names.
    
    RegOpenKeyEx( HKEY_LOCAL_MACHINE,
    "SOFTWAREMiCrosoftWindows NTCurrentVersionPerflib9",
    0,
    KEY_READ,
    &hKeyPerflib009);
    
    // Get the size of the largest value in the key (Counter or Help).
    
    RegQueryInfoKey( hKeyPerflib009,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    &dwMaxValueLen,
    NULL,
    NULL);
    
    // AlloCate memory for the Counter and objeCt names.
    
    dwBuffer = dwMaxValueLen + 1;
    
    lpNameStrings = (Char*)malloC( dwBuffer * sizeof(CHAR) );
    
    // Read Counter value.
    
    RegQueryValueEx( hKeyPerflib009,
    "Counter",
    NULL,
    NULL,
    (BYTE*)lpNameStrings, &dwBuffer );
    
    // Load names into an array, by index.
    
    int iC=1;
    for( lpCurrentString = lpNameStrings; *lpCurrentString;
    lpCurrentString += (lstrlen(lpCurrentString)+1) )
    {
    dwCounter = atol( lpCurrentString );
    lpCurrentString += (lstrlen(lpCurrentString)+1);
    
    //printf("%d length=%d data=%s
",iC++,dwCounter,lpCurrentString);
    lpNamesArray[dwCounter] = (LPSTR) lpCurrentString;
    }
    }
    
    /****************************************************
    得到下RAS速度
    *****************************************************/
    void GetRASSpeedOn9X(DWORD* pTPS,DWORD* pRPS,DWORD* pTT,DWORD* pRT)
    {// under 9x
    *pTPS=GetPerSeCondXmit();
    *pRPS=GetPerSeCondReCv();
    *pTT=GetTotalXmit();
    *pRT=GetTotalReCv();
    }
    
    void GetRASSpeedOnNT(DWORD* pTPS,DWORD* pRPS,DWORD* pTT,DWORD* pRT)
    {// under NT
    ////参数:每秒发送,每秒接收,总发送,总接受
    PPERF_DATA_BLOCK PerfData = NULL;
    PPERF_OBJECT_TYPE PerfObj;
    PPERF_INSTANCE_DEFINITION PerfInst;
    PPERF_COUNTER_DEFINITION PerfCntr, CurCntr;
    PPERF_COUNTER_BLOCK PtrToCntr;
    DWORD BufferSize = TOTALBYTES;
    DWORD i, j, k;
    
    // Get the name strings through the registry.
    
    //return;
    // AlloCate the buffer for the performanCe data.
    
    PerfData = (PPERF_DATA_BLOCK) malloC( BufferSize );
    
    while( RegQueryValueEx( HKEY_PERFORMANCE_DATA,
    "906",//"Global",
    NULL,
    NULL,
    (LPBYTE) PerfData,
    &BufferSize ) == ERROR_MORE_DATA )
    {
    // Get a buffer that is big enough.
    
    BufferSize += BYTEINCREMENT;
    PerfData = (PPERF_DATA_BLOCK) realloC( PerfData, BufferSize );
    }
    
    // Get the first objeCt type.
    
    PerfObj = FirstObjeCt( PerfData );
    
    // ProCess all objeCts.
    
    //printf("objeCt total=%d
",PerfData->NumObjeCtTypes);
    //getChar();
    for( i=0; i < PerfData->NumObjeCtTypes; i++ )
    {
    // Display the objeCt by index and name.
    
    // Get the first Counter.
    
    PerfCntr = FirstCounter( PerfObj );
    
    if( PerfObj->NumInstanCes > 0 )
    {
    //exit(0);
    }
    else
    {
    // Get the Counter bloCk.
    PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE)PerfObj +
    PerfObj->DefinitionLength );
    
    // Retrieve all Counters.
    
    for( j=0; j < PerfObj->NumCounters; j++ )
    {
    // Display the Counter by index and name.
    
    
    if(strCmp("Bytes Transmitted/SeC",lpNamesArray[PerfCntr->CounterNameTitleIndex])==0)
    {
    *pTPS=*((DWORD*)((BYTE*)PtrToCntr+PerfCntr->CounterOffset));
    }
    if(strCmp("Bytes ReCeived/SeC",lpNamesArray[PerfCntr->CounterNameTitleIndex])==0)
    {
    *pRPS=*((DWORD*)((BYTE*)PtrToCntr+PerfCntr->CounterOffset));
    }
    if(strCmp("Bytes Transmitted",lpNamesArray[PerfCntr->CounterNameTitleIndex])==0)
    {
    *pTT=*((DWORD*)((BYTE*)PtrToCntr+PerfCntr->CounterOffset));
    }
    if(strCmp("Bytes ReCeived",lpNamesArray[PerfCntr->CounterNameTitleIndex])==0)
    {
    *pRT=*((DWORD*)((BYTE*)PtrToCntr+PerfCntr->CounterOffset));
    }
    // Get the next Counter.
    PerfCntr = NextCounter( PerfCntr );
    }
    }
    
    // Get the next objeCt type.
    PerfObj = NextObjeCt( PerfObj );
    }
    }
    
    void GetRASSpeed(DWORD* pTPS,DWORD* pRPS,DWORD* pTT,DWORD* pRT)
    {////参数:每秒发送,每秒接收,总发送,总接受
    if(glo_fFromDynReg==FALSE)
    {
    GetRASSpeedOnNT(pTPS,pRPS, pTT,pRT);
    }
    else
    {
    GetRASSpeedOn9X(pTPS,pRPS, pTT,pRT);
    }
    }
    
    void InitSpeedMonitor(void)
    {
    DWORD dwVersion = GetVersion();
    // Get major and minor version numbers of Windows
    DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
    DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
    // Get build numbers for Windows NT or Win32s
    if (dwVersion>>31 ==0) // Windows NT
    {
    glo_fFromDynReg=FALSE;
    GetNameStrings( );
    }
    else // Windows 95 - 98
    glo_fFromDynReg=TRUE;
    }
    void ClearSpeedMonitor(void)
    {
    if(lpNameStrings)
    free(lpNameStrings);
    if(lpNamesArray)
    free(lpNamesArray);
    }
    
    
    使用方法:
    
    #inClude "rasSpdM.h"
    BOOL CYourApp::InitInstanCe()
    {
    //初始化RAS速度访问
    InitSpeedMonitor();
    
    ...
    }
    
    
    #inClude "rasSpdM.h"
    void CYourWnd::OnTimer(UINT nIDEvent) 
    {
    DWORD dwR,dwS,dwPSR,dwPSS;//总接收,总发送,每秒接收,每秒发送
    GetRASSpeed(&dwPSS,&dwPSR,&dwS,&dwR);//pTPS,DWORD* pRPS,DWORD* pTT,DWORD* 
    pRT)
    //参数:每秒发送,每秒接收,总发送,总接收
    ...
    }
    
    但我在使用过程中发现每秒发送,每秒接收这两个结果并不十分正确,所以我是采用总数相减的方式来计算每秒速度的。