zoukankan      html  css  js  c++  java
  • Delphi For Android 使用Posix函数获取网络信息(MAC, IP...)

    安卓中获取系统当前活动的网卡MAC地址和IP地址时,需要使用到java.net.networkinterface库,在Delphi中虽然可以调用java库,

    但是如果没有现成的java库(jar、class等),也会比较麻烦,这里使用posix函数实现获取MAC和IP地址,不需要root权限,

    但理论上应该需要设置查询网络状态和WIFI状态权限:

    <!-- 获取网络状态的权限 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    delphi的话在工程属性中勾选就好了。

    使用posix函数的方法,理论上支持android、ios、mac、linux...好处是很多的,而在android的NDK开发中也是使用这种方法实现,网上找一下就有代码。

    unit uNetWorkInfo;
    
    interface
    //注: posix的网络操作可参看indy控件的底层,如IdStackVCLPosix.pas
    //     posix大部分操作可参看linux相关代码,搜索linux代码即可翻译成pascal
    
    function getLocalMac(var sIP: string): string;
    
    implementation
    uses
      Posix.Base,
      Posix.ArpaInet,
      Posix.Errno,
      Posix.NetDB,
      Posix.NetIf,
      Posix.NetinetIn,
      Posix.StrOpts,
      Posix.SysTypes,
      Posix.SysUio,
      Posix.Unistd,
      Posix.SysSelect,
      Posix.SysSocket,
      Posix.SysTime,
      Posix.Stdio,
      Sockios,
      SysUtils;
    
    
    type
      TSunB = packed record
        s_b1, s_b2, s_b3, s_b4: Byte;
      end;
    
      TSunW = packed record
        s_w1, s_w2: Word;
      end;
    
      PIn4Addr = ^TIn4Addr;
      TIn4Addr = packed record
        case integer of
            0: (S_un_b: TSunB);
            1: (S_un_w: TSunW);
            2: (S_addr: LongWord);
      end;
    
      PIn6Addr = ^TIn6Addr;
      TIn6Addr = packed record
        case Integer of
        0: (s6_addr: packed array [0..16-1] of Byte);
        1: (s6_addr16: packed array [0..8-1] of Word);
      end;
    
    function IPv4AddrToString(const aInAddr: TIn4Addr): string;
    begin
      Result := IntToStr(TIn4Addr(AInAddr).S_un_b.s_b1) + '.'   {Do not Localize}
                + IntToStr(TIn4Addr(AInAddr).S_un_b.s_b2) + '.' {Do not Localize}
                + IntToStr(TIn4Addr(AInAddr).S_un_b.s_b3) + '.' {Do not Localize}
                + IntToStr(TIn4Addr(AInAddr).S_un_b.s_b4);
    end;
    
    // 获取本地mac
    function getLocalMac(var sIP: string): string;
    {$IFDEF POSIX}
    const
      MAXINTERFACES = 15;
    var
      sock_fd: integer;
      buf: array[0..MAXINTERFACES-1] of ifreq;
      ifc: ifconf;
      interface_num: integer;
      //M: TMarshaller;
      //sEn: string;
    {$ENDIF}
    begin
      {$IFDEF POSIX}
      sIP := '';
      Result := '';
    
      sock_fd := socket(AF_INET,
        SOCK_DGRAM, //SOCK_STREAM,
        0);
      if (sock_fd = -1) then
      begin
            //perror('create socket falise...mac
    ');
        Exit;
      end;
    
      FillChar(buf, SizeOf(buf), 0);
      ifc.ifc_len := sizeof(buf);
      ifc.ifc_ifcu.ifcu_req := @buf[0];
    
      (*
      //sEn := 'eth0';
      sEn := 'en0';
        Move(M.AsAnsi(sEn).ToPointer^, ifr_mac.ifrn_name, 4);
      *)
    
      if(ioctl(sock_fd, SIOCGIFCONF, @ifc) < 0) then
      begin
        Exit;
      end;
      interface_num := ifc.ifc_len div sizeof(ifreq);
    
      while interface_num>0 do
      begin
        Dec(interface_num);
    
        sIP := '';
        Result := '';
    
        if (ioctl(sock_fd, SIOCGIFFLAGS, @buf[interface_num])<0) then
        begin
          Continue;
        end;
        (*
            if(buf[interface_num].ifr_flags & IFF_PROMISC)
                printf("Interface is in promiscuous mode
    ");
        *)
        if ((buf[interface_num].ifr_ifru.ifru_flags and IFF_UP)<>0) and
           ((buf[interface_num].ifr_ifru.ifru_flags and IFF_RUNNING)<>0)and
           ((buf[interface_num].ifr_ifru.ifru_flags and IFF_LOOPBACK)=0) then
            //printf("Interface is running
    ");
        else
           Continue; //printf("Interface is not running
    ");
    
        //IP地址
        if (ioctl(sock_fd, SIOCGIFADDR, @buf[interface_num])<0) then
        begin
          Continue;
        end;
        if buf[interface_num].ifr_ifru.ifru_addr.sa_family<>AF_INET then //AF_INET6
          Continue;
        sIP := IPv4AddrToString(
          TIn4Addr(sockaddr_in(buf[interface_num].ifr_ifru.ifru_addr).sin_addr));
    
        //MAC地址
        if ((ioctl(sock_fd, SIOCGIFHWADDR, @buf[interface_num])) < 0) then
        begin
          //printf('mac ioctl error
    ');
          Result := '';
          Continue;
        end;
    
        Result := Format('%02X:%02X:%02X:%02X:%02X:%02X',
          [buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[0],
           buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[1],
           buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[2],
           buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[3],
           buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[4],
           buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[5]]
        );
        Break;
      end;
        FileClose(sock_fd);
      {$ELSE}
      //其他平台(如Windows,网上已经有很多代码了,可自行补充)
    sIP :
    = '0.0.0.0'; Result := '00:00:00:00:00:00'; {$ENDIF} end; end.

    由于delphi XE5/XE7...没有翻译sockios.h文件,因此此文件中的常量定义需要补充,Sockios.pas如下:

    unit Sockios;
    
    interface
    
    const
      FIOSETOWN =$8901;
      SIOCSPGRP =$8902;
      FIOGETOWN =$8903;
      SIOCGPGRP =$8904;
      SIOCATMARK =$8905;
      SIOCGSTAMP =$8906;
    
      //SIOCINQ = FIONREAD;
      //SIOCOUTQ = TIOCOUTQ;
    
      SIOCADDRT =$890B;
      SIOCDELRT =$890C;
      SIOCRTMSG =$890D;
    
      SIOCGIFNAME =$8910;
      SIOCSIFLINK =$8911;
      SIOCGIFCONF =$8912;
      SIOCGIFFLAGS =$8913;
      SIOCSIFFLAGS =$8914;
      SIOCGIFADDR =$8915;
      SIOCSIFADDR =$8916;
      SIOCGIFDSTADDR =$8917;
      SIOCSIFDSTADDR =$8918;
      SIOCGIFBRDADDR =$8919;
      SIOCSIFBRDADDR =$891a;
      SIOCGIFNETMASK =$891b;
      SIOCSIFNETMASK =$891c;
      SIOCGIFMETRIC =$891d;
      SIOCSIFMETRIC =$891e;
      SIOCGIFMEM =$891f;
      SIOCSIFMEM =$8920;
      SIOCGIFMTU =$8921;
      SIOCSIFMTU =$8922;
      SIOCSIFNAME =$8923;
      SIOCSIFHWADDR =$8924;
      SIOCGIFENCAP =$8925;
      SIOCSIFENCAP =$8926;
      SIOCGIFHWADDR =$8927;
      SIOCGIFSLAVE =$8929;
      SIOCSIFSLAVE =$8930;
      SIOCADDMULTI =$8931;
      SIOCDELMULTI =$8932;
      SIOCGIFINDEX =$8933;
      SIOGIFINDEX =SIOCGIFINDEX;
      SIOCSIFPFLAGS =$8934;
      SIOCGIFPFLAGS =$8935;
      SIOCDIFADDR =$8936;
      SIOCSIFHWBROADCAST =$8937;
      SIOCGIFCOUNT =$8938;
      SIOCKILLADDR =$8939;
    
      SIOCGIFBR =$8940;
      SIOCSIFBR =$8941;
    
      SIOCGIFTXQLEN =$8942;
      SIOCSIFTXQLEN =$8943;
    
      SIOCETHTOOL =$8946;
    
      SIOCGMIIPHY =$8947;
      SIOCGMIIREG =$8948;
      SIOCSMIIREG =$8949;
    
      SIOCWANDEV =$894A;
    
      SIOCDARP =$8953;
      SIOCGARP =$8954;
      SIOCSARP =$8955;
    
      SIOCDRARP =$8960;
      SIOCGRARP =$8961;
      SIOCSRARP =$8962;
    
      SIOCGIFMAP =$8970;
      SIOCSIFMAP =$8971;
    
      SIOCADDDLCI =$8980;
      SIOCDELDLCI =$8981;
    
      SIOCGIFVLAN =$8982;
      SIOCSIFVLAN =$8983;
    
      SIOCBONDENSLAVE =$8990;
      SIOCBONDRELEASE =$8991;
      SIOCBONDSETHWADDR =$899;
      SIOCBONDSLAVEINFOQUERY =$8993;
      SIOCBONDINFOQUERY =$8994;
      SIOCBONDCHANGEACTIVE =$8995;
    
      SIOCBRADDBR =$89a0;
      SIOCBRDELBR =$89a1;
      SIOCBRADDIF =$89a2;
      SIOCBRDELIF =$89a3;
    
      SIOCDEVPRIVATE =$89F0;
    
      SIOCPROTOPRIVATE =$89E0;
    
    implementation
    
    end.
  • 相关阅读:
    Android内存优化5 了解java GC 垃圾回收机制3
    一起刑事案件法庭辩护 z
    辩护技巧总结——律师在刑事辩护中应注意的几个问题 z
    证据对抗、证据链标准 z
    里德九步审讯法 z
    WCF服务在高并发情况下报目标积极拒绝的异常处理 z
    C#EasyHook例子C# Hook 指定进程C#注入指定进程 z
    玄机论坛Socket类库源码 当前版本 2.6.3 更新日期:10-09/2015 z
    庭审全程文字实录 z
    庭审精彩语录整理 z
  • 原文地址:https://www.cnblogs.com/caibirdy1985/p/4444988.html
Copyright © 2011-2022 走看看