多網卡擷取IP之VC篇

來源:互聯網
上載者:User

方法:C語言擷取網卡方法之WSAIoctl函數
在WinSock中可以通過調用WSAIoctl()函數,通過設定標誌為SIO_GET_INTERFACE_LIST 的方法擷取網路介面資訊。其函數在MSDN定義如下:

int WSAIoctl(
  SOCKET s,  // SOCKET控制代碼
  DWORD dwIoControlCode,  // 控制碼,SIO_GET_INTERFACE_LIST在MSDN中並沒有是通過宏定義計算轉換的
  LPVOID lpvInBuffer, // 輸入緩衝區的地址
  DWORD cbInBuffer,// 出入緩衝區的大小
  LPVOID lpvOutBuffer,// 輸出緩衝區地址
  DWORD cbOutBuffer,// 輸出緩衝區大小
  LPDWORD lpcbBytesReturned,// 實際輸出位元組數地址
  LPWSAOVERLAPPED lpOverlapped,// WSAOVERLAPPED結構的地址  
  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // 操作結束後調用的曆程指標
);


該函數定義在ws2tcpip.h中所以要先包含該標頭檔,另外需要提到的就是儲存資訊結構體,如下:

typedef struct _INTERFACE_INFO
{
    u_long             iiFlags;// 介面的類型和狀態
    struct sockaddr    iiAddress;// 介面IP地址
    struct sockaddr    iiBroadcastAddress; // 介面對應的廣播位址
    struct sockaddr    iiNetmask;  // 介面對應的子網路遮罩
} INTERFACE_INFO;

實現的核心代碼如下:

//
// 返回通訊端資訊結構體,參數type:type=-1表示列出所有網卡資訊,不等於-1則是選擇指定網卡顯示
//

int GetIoInfo(int type)
{
  int ret;
  int nFace; // IoInfo個數
  int i;
  SOCKET InfoSock;
  // 儲存實際的網卡介面資訊位元組數
  DWORD BytesReturned;
  InfoSock=WSASocket(AF_INET,SOCK_DGRAM,0,0,0,0);
  if(INVALID_SOCKET==InfoSock)
  {
    printf("WSASocket Error:%s\n",WSAGetLastError());
    return 0;
  }
  // 設定標誌SIO_GET_INTERFACE_LIST表示擷取網路介面資訊
  ret=WSAIoctl(InfoSock,SIO_GET_INTERFACE_LIST,0,0,&IOInfo,sizeof(IOInfo),&BytesReturned,0,0);
  if(SOCKET_ERROR==ret)
  {
    printf("WSAIoctl Error:%s\n",WSAGetLastError());
    return 0;
  }
  // 計算網卡介面資訊個數
  nFace=BytesReturned/sizeof(INTERFACE_INFO);

  // type=-1   -- List All Adapter Infomation
  // type!=-1  -- List the Number [type] Adapter Information
  switch(type)
  {
    case -1:
    {
      for(i=0;i<nFace;i++)   // 迴圈輸出所有網路介面資訊
      {
        printf("\nThe %d NetInterFace Information:\n",i);
        // 得到網卡地址,並將IP格式轉換為字串格式輸出
        printf("IP Address:%s\n",inet_ntoa(IOInfo[i].iiAddress.AddressIn.sin_addr));
      }
      return 1;
      break;
    }
    default:
      {
        if(type<nFace&&type>=0){
          printf("\nThe %d NetInterFace Information:\n",type);
          // 得到網卡地址,並將IP格式轉換為字串格式輸出
          printf("IP Address:%s\n",inet_ntoa(IOInfo[type].iiAddress.AddressIn.sin_addr));
        }else{
          printf("The Net InteFace %d is Not Found!\n",type);
          return 0;
        }
        return 1;
        break;
      }
  }
  return 1;
}

方法:C語言擷取網卡方法之GetAdaptersInfo函數
接著上一篇,我們通過第二種方法實現,這種方法擷取到資訊更加完整,也比較實際應用。主要函數是GetAdaptersInfo,該函數在在標頭檔iphlpapi.h中提供的。但是有個問題該檔案在預設只安裝VC6.0的環境下是沒有,他被包含在platform SDK(軟體開發包)中,我從安裝的SDK包提取出包含的檔案頭及相關檔案直接放在開發目錄下就可以了。在文章的最後會給出下載。
首先瞭解下GetAdaptersInfo函數:

DWORD GetAdaptersInfo(
  // 接受資料的緩衝區,指向一個結構IP_ADAPTER_INFO
  PIP_ADAPTER_INFO pAdapterInfo,  
  // 指向輸出緩衝區的大小的指標
  PULONG pOutBufLen              
);

這個函數中最重要是第一個參數,看看這個結構有點啥?MSDN中說明如下:

typedef struct _IP_ADAPTER_INFO {
  struct _IP_ADAPTER_INFO* Next; // 鏈表指標,指向下一個單元
  DWORD ComboIndex;
  char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; // 介面資訊實體名稱
  char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];// 介面描述資訊
  UINT AddressLength; // MAC地址的長度
  BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]; // MAC地址
  DWORD Index;
  UINT Type;
  UINT DhcpEnabled;
  PIP_ADDR_STRING CurrentIpAddress;
  IP_ADDR_STRING IpAddressList;  // IP地址清單
  IP_ADDR_STRING GatewayList;   // 網關地址清單
  IP_ADDR_STRING DhcpServer;   // DHCP地址
  BOOL HaveWins;
  IP_ADDR_STRING PrimaryWinsServer;   // 首選WINS 伺服器
  IP_ADDR_STRING SecondaryWinsServer; // 備用WINS伺服器
  time_t LeaseObtained;
  time_t LeaseExpires;
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;

在上面我只介紹了幾個常用的參數。這些參數足以了。下面看下實現的小例子,代碼如下:

#include "stdafx.h"
#include "winsock.h"
#include "stdio.h"
#include "iphlpapi/iphlpapi.h" // GetAdaptersInfo()
#pragma comment(lib,"iphlpapi/iphlpapi.lib")

int main(int argc, char* argv[])
{
  // 網路介面資訊,最多20個
  IP_ADAPTER_INFO IOInfo[20];
  // 鏈表結構指標初始化
  PIP_ADAPTER_INFO pIOInfo=NULL;
  DWORD Result=0;
  // 擷取大小
  unsigned long nLen=sizeof(IOInfo);
  // 擷取網卡資訊
  Result=GetAdaptersInfo(IOInfo,&nLen);
  if(NO_ERROR!=Result)
  {
    printf("GetAdaptersInfo Error.\n");
    return 0;
  }else{
    pIOInfo=IOInfo; // 將鏈表指標指向網路介面資訊儲存結構
    while(pIOInfo!=NULL)  // 不為空白就迴圈讀取網卡
    {
      static int Num;
      Num++;
      printf("\n┌────────────Num.%d────────────┐\n",Num);
      printf("│Name:%s\n",pIOInfo->AdapterName);
      printf("│Desc:%s\n",pIOInfo->Description);
      printf("│IP:%s\n",pIOInfo->IpAddressList.IpAddress.String);
      printf("│MAC:%02X:%02X:%02X:%02X:%02X:%02X\n",pIOInfo->Address[0],pIOInfo->Address[2],pIOInfo->Address[3],pIOInfo->Address[4],pIOInfo->Address[5]);
      printf("│GateWay:%s\n",pIOInfo->GatewayList.IpAddress.String);
      printf("└────────────Num.%d────────────┘\n",Num);
      // 鏈表指標指向下一個
      pIOInfo=pIOInfo->Next;
    }
  }
  return 0;
}

方法三:hostent結構遍曆

#include "stdio.h"
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib")

int main(int argc, char* argv[])
{
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;
 
  wVersionRequested = MAKEWORD( 2, 2 );
 
  err = WSAStartup( wVersionRequested, &wsaData );
  if ( err != 0 ) {                            
    return 0;
  }
  if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 2 ) {
    WSACleanup( );
  }
 
  char host[255];
  memset(host,0,255);
  gethostname(host,255);
  printf("%s\n",host);
 
 
  struct hostent *Host;
  Host=gethostbyname(host);
  struct in_addr addr;
  for(int i=0;;i++){
    if(Host->h_addr_list[i]!='\0'){
      memmove(&addr,Host->h_addr_list[i],4);
      char *ip;
      ip=inet_ntoa(addr);
      printf("ip:%s\n",ip);
    }else{
      break;
    }
  }
  WSACleanup();
 
  return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.