////////
....
m_socket.SendTo((void*)bs,50,NBTSTATPORT,ip,0);  
///////
....
m_socket.ReceiveFrom(Buf,500,strIP,dport,0);
我用以上方法,分析BUF查看局域网中机器的MAC地址,大部分MAC地址能正常显示,但是部分MAC地址的最后1位或2位不能显示,或者整个地址不能显示。
但是用arp -a 命令正常!

解决方案 »

  1.   

    我在本机上用查看注册表的方法也能正确得到MAC地址。
      

  2.   

    ********************************取得本地MAC地址********************************#include <lm.h>
    #pragma comment(lib,"NetApi32.lib")void CDDlg::OnButton2() 
    {
    unsigned char macdata[8];
    WKSTA_TRANSPORT_INFO_0 * pwkti;
    DWORD dwe,dwt;
    BYTE *pb;
    NET_API_STATUS dws=NetWkstaTransportEnum(
    NULL,
    0,
    &pb,
    MAX_PREFERRED_LENGTH,
    &dwe,
    &dwt,
    NULL);
    pwkti=(WKSTA_TRANSPORT_INFO_0 *)pb;
    CString cs;
    for(DWORD i=1;i<dwe;i++)
    {
    swscanf((wchar_t *)pwkti[i].wkti0_transport_address,L"%2hx%2hx%2hx%2hx%2hx%2hx",&macdata[0],
    &macdata[1],&macdata[2],&macdata[3],&macdata[4],&macdata[5]);
    cs.Format("%02x%02x%02x%02x%02x%02x",macdata[0],
    macdata[1],macdata[2],macdata[3],macdata[4],macdata[5]);
    MessageBox(cs);
    }
    NetApiBufferFree(pb);
    }
      

  3.   

    1.you can use sendarp function to get mac address in local.
    2.if you want to use netbios code,give you an example:
    / ResolveThread.cpp : implementation file
    //#include "stdafx.h"
    #include <nb30.h>
    #include <string.h>
    #include "pinger.h"
    #include "ResolveThread.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CResolveThreadIMPLEMENT_DYNCREATE(CResolveThread, CWinThread)CResolveThread::CResolveThread()
    {
    m_dwTimeout = 2000;
    m_dwCount = 3;
    }CResolveThread::CResolveThread(DWORD dwTimeout, DWORD dwCount)
    {
    m_dwTimeout = dwTimeout;
    m_dwCount = dwCount;
    }CResolveThread::~CResolveThread()
    {
    }BOOL CResolveThread::InitInstance()
    {
    // TODO:  perform and per-thread initialization here
    m_sockNbt = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (INVALID_SOCKET == m_sockNbt)
    {
    return FALSE;
    } int nTimeout = (int)m_dwTimeout;
    if (SOCKET_ERROR == setsockopt(m_sockNbt, SOL_SOCKET, SO_SNDTIMEO, (char*)(&nTimeout), sizeof(nTimeout)))
    {
    closesocket(m_sockNbt);
    return FALSE;
    }

    m_nUniID = (USHORT)m_nThreadID; return TRUE;
    }int CResolveThread::ExitInstance()
    {
    // TODO:  perform any per-thread cleanup here
    return CWinThread::ExitInstance();
    }BEGIN_MESSAGE_MAP(CResolveThread, CWinThread)
    //{{AFX_MSG_MAP(CResolveThread)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    ON_THREAD_MESSAGE(UM_RESOLVE_HOST_NAME, OnResolveHostName)
    ON_THREAD_MESSAGE(UM_DESTROY_THREAD, OnDestroyThread)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CResolveThread message handlersvoid CResolveThread::OnResolveHostName(WPARAM /* wParam */, LPARAM lParam)
    {
    RESOLVE_HOST_NAME_MESSAGE * pResolveHostNameMessage = (RESOLVE_HOST_NAME_MESSAGE *)lParam;
    DWORD dwIpAddress = pResolveHostNameMessage->dwIpAddress; sockaddr_in to_addr;
    sockaddr_in from_addr;
    int from_addr_len = sizeof(from_addr);
    to_addr.sin_addr.s_addr = dwIpAddress;
    to_addr.sin_port = htons(137);
    to_addr.sin_family = AF_INET; NBTSTAT_REQUEST_PACKET * pRequest = (NBTSTAT_REQUEST_PACKET*)m_pSendBuf;
    memset(pRequest, 0, sizeof(NBTSTAT_REQUEST_PACKET));
    pRequest->question_count = htons(1);
    pRequest->name_len = 0x20;
    memcpy(pRequest->name, NETBIOS_QUERY_NAME, 32);
    pRequest->type = htons(0x21);
    pRequest->protocol = htons(1); BOOL bNetBiosNameResolved = FALSE; for (DWORD i=0; i<3/*m_dwCount*/; i++)
    {
    int nRet;
    int nTimeout = (int)m_dwTimeout; pRequest->id = ++m_nUniID; if (SOCKET_ERROR == sendto(m_sockNbt, (char*)m_pSendBuf, sizeof(NBTSTAT_REQUEST_PACKET), 0, (struct sockaddr*)(&to_addr), sizeof(to_addr)))
    {
    continue;
    } if (SOCKET_ERROR == setsockopt(m_sockNbt, SOL_SOCKET, SO_RCVTIMEO, (char*)(&nTimeout), sizeof(nTimeout)))
    {
    continue;
    } nRet = recvfrom(m_sockNbt, (char*)m_pRecvBuf, BUFFER_SIZE, 0, (struct sockaddr*)(&from_addr), &from_addr_len);
    if (nRet == SOCKET_ERROR)
    {
    continue;
    }
    else
    {
    PNBTSTAT_RESPONSE_HEADER pResponseHeader = (PNBTSTAT_RESPONSE_HEADER)m_pRecvBuf;
    PNETBIOS_NAME_ENTRY pNameEntry = (PNETBIOS_NAME_ENTRY)(m_pRecvBuf + sizeof(NBTSTAT_RESPONSE_HEADER));
    if (pResponseHeader->id == m_nUniID && pResponseHeader->name_number != 0 && pResponseHeader->name_number < 64 && pNameEntry->name_term == 0)
    {
    CHAR szNetBiosName[64]; char * pNameEnd = strchr((char*)(pNameEntry->name), 0x20);
    if (NULL != pNameEnd) 
    {
    pNameEnd[0] = 0;
    }
    else
    {
    szNetBiosName[15] = 0;
    } strncpy(szNetBiosName, (char*)(pNameEntry->name), 15); for (USHORT j=0; j<pResponseHeader->name_number; j++)
    {
    if (0 == memcmp(pNameEntry[j].name, "\x01\x02__MSBROWSE__\x02\x01", 16))
    {
    strcat(szNetBiosName, "!");
    }
    } *(pResolveHostNameMessage->pstrHostName) = szNetBiosName;
    bNetBiosNameResolved = TRUE;
    break;
    }
    }
    }
    /*
    if (FALSE == bNetBiosNameResolved)
    {
    HOSTENT * pHostEnt = gethostbyaddr((char*)&dwIpAddress, sizeof(dwIpAddress), AF_INET);
    if (NULL != pHostEnt)
    {
    *(pResolveHostNameMessage->pstrHostName) = pHostEnt->h_name;
    }
    }
    */
    SetEvent(pResolveHostNameMessage->hEvent);
    }void CResolveThread::OnDestroyThread(WPARAM wParam, LPARAM lParam)
    {
    PostThreadMessage(WM_QUIT, 0, 0);
    }
      

  4.   

    To oyljerry:我如果只查那台出问题的机器也是同样问题,我用的是多线程。
    To dbafans:这种方法只能得到本机的IP,我是想通过分析IP包,查看局域网中其他机的MAC地址。不过还是谢谢你!
      

  5.   

    To kingzai:你的代码我再研究一下,不过不知道你知不知到,我那种情况出现是怎么回事,代码应该是没有问题,因为大多数机的代码都正常。
      

  6.   

    use getlasterror to get detail