比如说当http://www.163.com给我所在的主机发送数据包时,如何取得远程主机(www.163.com)网卡的MAC 地址?
用winpcap编程的代码如下:d->name表示设备的名称,d->description表示设备的描述,那么怎么取得MAC地址呢?
#include "pcap.h"main()
{
    pcap_if_t *alldevs;
    pcap_if_t *d;
    int i=0;
    char errbuf[PCAP_ERRBUF_SIZE];
    
    /* Retrieve the device list *//*取得网卡列表*/
    if (pcap_findalldevs(&alldevs, errbuf) == -1)
    {
        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }
    
    /* Print the list */
    for(d=alldevs;d;d=d->next)
    {
        printf("%d. %s", ++i, d->name);
        if (d->description)
            printf(" (%s)\n", d->description);
        else            printf(" (No description available)\n");
    }
    
    if(i==0)
    {
        printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
        return;
    }    /* We don't need any more the device list. Free it */
    pcap_freealldevs(alldevs);
}在WIND2000下,输出结果如下:
1. {4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS) Ethernet Adapter) 
2. {5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI) 

解决方案 »

  1.   

    刚才查了一下资料:只能查到局域网中的MAC地址:在底层的网络通信中,两个节点想要相互通信,必须先要知道源与目标的MAC地址。为了让系统能快速地找到一个远程节点的MAC地址,每一个本地的内核都保存有一个即时的查询表(称为ARP缓存)。ARP中有影射远程主机的IP地址到其对应的MAC地址的一个列表。地址解析协议(ARP)缓存是一个常驻内存的数据结构,其中的内容是由本地系统的内核来管理和维护的。默认的情况下,ARP缓存中保留有最近十分钟本地系统与之通信的节点的IP地址(和对应的MAC地址)。
    当一个远程主机的MAC地址存在于本地主机的ARP 缓存中,转换远程节点的IP地址为MAC地址不会遇到问题。然而在许多情况下,远程主机的MAC地址并不存在于本地的ARP缓存中,系统会怎么处理呢?在知道一个远程主机的IP地址,但是MAC地址不在本地的ARP缓存中的时候,以下的过程用来获取远程节点的MAC地址:本地主机发送一个广播包给网络中的所有的节点,询问是否有对应的IP地址。一个节点(只有一个)会回答这个ARP广播信息。在回应的信息包里就会包含有这个远程主机的MAC地址。在收到这个返回包后,本地节点就会在本地ARP缓存中记录远程节点的MAC地址
      

  2.   

    局域网中,如何通过ARP协议得到其他主机MAC地址?
    // rmac.cpp : 定义控制台应用程序的入口点。
    //#include "stdafx.h"
    #include "afxsock.h"
    #include <iphlpapi.h>  //ip helper lib需要最新的MS paltform SDK 或者使用VC7
    #include "rmac.h"
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    // 唯一的应用程序对象CWinApp theApp;using namespace std;
    #pragma comment ( lib, "ws2_32.lib" )
    #pragma comment ( lib, "Iphlpapi.lib" )void doFunction( int argc, char ** argv )
    {
        int numberOfHost = 1;
        struct hostent *remoteHostent;    //处理命令行参数
        if ( argc == 3 )
            numberOfHost = atoi( argv[2] );
        if ( ( argc >3 ) || ( argc < 2 ) )
        {
            printf( "RmtHost v0.2 - Get remote HostName /MacAddress\n" );
            printf( "by ShotgunLabs ( [email protected] )\n\n" );
            printf( "Usage :\n\tRmtHost.exe [RemoteIP]\n\n" );
            printf( "Example:\n\tRmtHost.exe 192.168.0.3\n" );
            printf( "\tRmtHost.exe 192.168.0.3 255\n\n" );
            exit( 0 );
        }
        //初始化SOCKET
        WSADATA wsaData;
        int iRet = WSAStartup(MAKEWORD(2,1), &wsaData);
        if ( iRet != 0 )
        {
            printf( "WSAStartup Error:%d\n", GetLastError() );
            exit( 0 );
        }
        int nRemoteAddr = inet_addr( argv[1] );
        remoteHostent= (struct hostent*)malloc( sizeof(struct hostent ));
        struct in_addr sa;
        for ( int i = 0; i < numberOfHost; i ++ )
        {
            //获取远程机器名
            sa.s_addr = nRemoteAddr;
            printf( "\nIpAddress : %s\n", inet_ntoa( sa ) );
            remoteHostent = gethostbyaddr( (char*)&nRemoteAddr,4, AF_INET );
            if ( remoteHostent )
                printf( "HostName : %s\n",remoteHostent->h_name );
            else
                printf( "gethostbyaddr Error:%d\n",GetLastError() );
            //发送ARP查询包获得远程MAC地址        unsigned char macAddress[6];
            ULONG macAddLen = 6;
            iRet=SendARP(nRemoteAddr, (unsigned long)NULL,(PULONG)&macAddress, &macAddLen);
            if ( iRet == NO_ERROR )
            {
                printf( "MacAddress: " );
                for( int i =0; i<6; i++ )
                {
                    printf( "%.2x", macAddress[i] );
                    if ( i<5 ) printf( "-" );
                }
                printf( "\n" );
            }
            else
                printf( "SendARP Error:%d\n", GetLastError());
            nRemoteAddr = htonl( ntohl( nRemoteAddr ) + 1 );
        }
    }
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
        int nRetCode = 0;    // 初始化 MFC 并在失败时显示错误
        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
        {
            // TODO: 更改错误代码以符合您的需要
            _tprintf(_T("致命错误:MFC 初始化失败\n"));
            nRetCode = 1;
        }
        else
        {
            // TODO: 在此处为应用程序的行为编写代码。
            doFunction(argc,argv);
        }    return nRetCode;
    }
      

  3.   

    只能去局域网的mac
    http://www.zgtcc.com/upload/files/xinxi/F:XBakX20030305XNetAdminXNetAdminXLib.zip
      

  4.   

    你可以先 ping它,它会有个返回包,用winpcap捕包,可以取到这个包的mac地址。不过,我没有在外网上试过
      

  5.   

    除非目标机明确把MAC地址当数据发送给你,否则不可能得到。ARP协议只能在一个网段内有效。
      

  6.   

    当IP数据包通过路由器时,它会将源MAC地址换成自己的地址,IP地址不变,这样每到一台新的路由器时,帧里的源MAC地址都被替换,也就是说,你得到只是你所连接的路由器的MAC地址。
      

  7.   


    可以试试这段代码,
    //得到服务器的IP地址列表(只需要第一个即可)
    pHost=::gethostbyname(strServer);
    LPCSTR psz;
    if (pHost==NULL)
    {
    MessageBox(NULL,"网络连接失败!请稍后再试。","NewsBoy",MB_OK);
    return "";
    }
    else
    //转换为IP地址
    psz=inet_ntoa (*(struct in_addr *)pHost->h_addr_list[0]);
      

  8.   

    不可能。
    你上网,你的主机是与电信(或其他)的主机连接,这两台机子相当于在一个局域网中,然后数据还要通过好多主机,路由器才能到你要访问的服务器。
    你所能得到的MAC地址最多是电信主机的MAC地址。MAC地址是在局域网使用的,在主干网上,一些数据是直接在IP层传输的,那数据报中就连MAC地址都没有。
      

  9.   

    哪儿有wincap的用法?????我找不到
      

  10.   

    winpcap官方网站:http://winpcap.polito.it/
      

  11.   

    没有一种100%可行的办法满足你的需求。有一些办法不是很完美
    1)如果在局域网中,可以使用ARP解析得到目的主机的MAC地址,这个方法只限于局域网内,相同网段的主机有效,不同子网的ARP请求只能得到网关的MAC地址。相关的API:
    CreateIpNetEntry 
    CreateProxyArpEntry 
    DeleteIpNetEntry 
    DeleteProxyArpEntry 
    FlushIpNetTable 
    GetIpNetTable 
    SendARP 
    SetIpNetEntry 2)如果目的主机使用了WINS服务器,你可以把自己的机器设置成使用相同的WINS服务器,然后使用NBTSTAT -A 命令行就可以得到目的主机的MAC地址2)如果目的主机在公网上,也不是说完全不可能得到它的MAC地址,但是要有一些条件限制:
    目的主机与你相连的的网络接口是以太网接口或者PPPOE接口;
    目的主机打开了137端口;
    你与目的主机之间的网络互连设备没有设置NETBIOS过滤的ACL;
    这种条件下,可以通过NetBIOS name query得到目的主机的MAC地址。
    代码如下:
    头文件:
    #if !defined(AFX_RESOLVETHREAD_H__325B3F03_E8F6_4B98_81D3_19C32CADCA21__INCLUDED_)
    #define AFX_RESOLVETHREAD_H__325B3F03_E8F6_4B98_81D3_19C32CADCA21__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // ResolveThread.h : header file
    //#define NETBIOS_QUERY_NAME  "\x43\x4b\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"#pragma pack(1)typedef struct tagNBTSTAT_REQUEST_PACKET
    {
    USHORT id;
    USHORT flag;
    USHORT question_count;
    USHORT answer_count;
    USHORT authority_count;
    USHORT additional_record_count;
    UCHAR name_len;
    UCHAR name[32];
    UCHAR name_term;
    USHORT type;
    USHORT protocol;
    } NBTSTAT_REQUEST_PACKET, *PNBTSTAT_REQUEST_PACKET;typedef struct tagNBTSTAT_RESPONSE_HEADER
    {
    USHORT id;
    USHORT flag;
    USHORT question_count;
    USHORT answer_count;
    USHORT authority_count;
    USHORT additional_record_count;
    UCHAR name_len;
    UCHAR name[32];
    UCHAR name_term;
    USHORT type;
    USHORT protocol;
    ULONG time_to_live;
    USHORT length;
    UCHAR name_number;
    } NBTSTAT_RESPONSE_HEADER, *PNBTSTAT_RESPONSE_HEADER;typedef struct tagNETBIOS_NAME_ENTRY
    {
    UCHAR name[16];
    UCHAR name_flag;
    UCHAR name_term;
    } NETBIOS_NAME_ENTRY, *PNETBIOS_NAME_ENTRY;typedef struct tagNBTSTAT_RESPONSE_TAIL
    {
    UCHAR unit_id[6];
    UCHAR jumpers;
    UCHAR test_result;
    USHORT version_number;
    USHORT period_of_statistics;
    USHORT number_of_crcs;
    USHORT number_alignment_errors;
    USHORT number_of_collisions;
    USHORT number_send_abort;
    ULONG number_good_sends;
    ULONG number_good_receives;
    USHORT number_retransmits;
    USHORT number_no_resource_conditions;
    USHORT number_free_command_blocks;
    USHORT total_number_command_blocks;
    USHORT max_total_number_command_blocks;
    USHORT number_pending_sessions;
    USHORT max_number_pending_sessions;
    USHORT max_total_session_possible;
    USHORT session_data_packet_size;
    } NBTSTAT_RESPONSE_TAIL, *pNBTSTAT_RESPONSE_TAIL;#pragma pack()typedef struct tagRESOLVE_HOST_NAME_MESSAGE
    {
    DWORD dwIpAddress;
    CString * pstrHostName;
    DWORD dwResult;
    HANDLE hEvent;
    } RESOLVE_HOST_NAME_MESSAGE;/////////////////////////////////////////////////////////////////////////////
    // CResolveThread threadclass CResolveThread : public CWinThread
    {
    DECLARE_DYNCREATE(CResolveThread)
    public:
    CResolveThread();           // protected constructor used by dynamic creation
    CResolveThread(DWORD dwTimeout, DWORD dwCount);
    virtual ~CResolveThread();// Attributes
    public:// Operations
    public:// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CResolveThread)
    public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
    //}}AFX_VIRTUAL// Implementation
    protected: // Generated message map functions
    //{{AFX_MSG(CResolveThread)
    // NOTE - the ClassWizard will add and remove member functions here.
    afx_msg void OnResolveHostName(WPARAM wParam, LPARAM lParam);
    afx_msg void OnDestroyThread(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG DECLARE_MESSAGE_MAP()
    public:
    UCHAR m_pSendBuf[BUFFER_SIZE];
    UCHAR m_pRecvBuf[BUFFER_SIZE];
    SOCKET m_sockNbt;
    DWORD m_dwTimeout;
    DWORD m_dwCount;
    USHORT m_nUniID;
    };///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_RESOLVETHREAD_H__325B3F03_E8F6_4B98_81D3_19C32CADCA21__INCLUDED_)
      

  12.   

    实现文件:
    // 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);
    }
      

  13.   

    这个问题以前有人问过,楼主可以找一找。至于解决方法,我好像在那本杂志上看过,“计算机世界”??,忘了名字了。大概的方法是这样子的:通过SNMP访问路由器来查询。
      

  14.   

    可以用NetBIOS获得M局域网内主机MAC地址。大家都没有用NetBIOS,是不是现在已经不用这个了吗?
      

  15.   

    得到远程机器MAC地址源代码http://www.chinaoak.com/download/sources/network/RenoteMAC.doc
      

  16.   

    http://www.chinaoak.com/download/sources/network/RenoteMAC.doc行不行,我不太會,請高手試試, 謝謝!!!
      

  17.   

    通过ARP协议是不行了,因为arp协议包是没有IP地址的,所以不可路由,根本不可能在路由器间转发。snmp可能是可行途径,但我对snmp不了解。
      

  18.   

    翻出一个代码,留个EMAIL到我消息里,发给你