`
hac103
  • 浏览: 41848 次
  • 性别: Icon_minigender_1
  • 来自: 南宁
社区版块
存档分类
最新评论

java取客户mac地址

    博客分类:
  • JAVA
阅读更多

NND,很多人都不装插件,没办法只能想另外的办法取mac。网上(http://wangxuliangboy.iteye.com/blog/374298)找了一下代码回来改,只改了部分先存在这里

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

//import javax.servlet.http.HttpServletRequest;
/**
 * 主机A向主机B发送“UDP-NetBIOS-NS”询问包,即向主机B的137端口,发Query包来询问主机B的NetBIOS Names信息。
 * 其次,主机B接收到“UDP-NetBIOS-NS”询问包,假设主机B正确安装了NetBIOS服务........... 而且137端口开放,则主机B会向主机A发送一个“UDP-NetBIOS-NS”应答包,即发Answer包给主机A。
 * 并利用UDP(NetBIOS Name Service)来快速获取远程主机MAC地址的方法
 * 
 * 
 */

public class UdpGetClientMacAddr {

    private String         sRemoteAddr;
    private int            iRemotePort = 137;
    private byte[]         buffer      = new byte[1024];
    private DatagramSocket ds          = null;

    public UdpGetClientMacAddr(String strAddr) throws Exception {
        sRemoteAddr = strAddr;
        ds = new DatagramSocket();
    }

    protected final DatagramPacket send(final byte[] bytes) throws IOException {
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(sRemoteAddr), iRemotePort);
        ds.setSoTimeout(2000);
        ds.send(dp);
        return dp;
    }

    protected final DatagramPacket receive() throws Exception {
        DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
        ds.receive(dp);
        return dp;
    }

    // 询问包结构:
    // Transaction ID 两字节(16位) 0x00 0x00
    // Flags 两字节(16位) 0x00 0x10
    // Questions 两字节(16位) 0x00 0x01
    // AnswerRRs 两字节(16位) 0x00 0x00
    // AuthorityRRs 两字节(16位) 0x00 0x00
    // AdditionalRRs 两字节(16位) 0x00 0x00
    // Name:array [1..34] 0x20 0x43 0x4B 0x41(30个) 0x00 ;
    // Type:NBSTAT 两字节 0x00 0x21
    // Class:INET 两字节(16位)0x00 0x01
    protected byte[] GetQueryCmd() throws Exception {
        byte[] t_ns = new byte[50];
        t_ns[0] = 0x00;
        t_ns[1] = 0x00;
        t_ns[2] = 0x00;
        t_ns[3] = 0x10;
        t_ns[4] = 0x00;
        t_ns[5] = 0x01;
        t_ns[6] = 0x00;
        t_ns[7] = 0x00;
        t_ns[8] = 0x00;
        t_ns[9] = 0x00;
        t_ns[10] = 0x00;
        t_ns[11] = 0x00;
        t_ns[12] = 0x20;
        t_ns[13] = 0x43;
        t_ns[14] = 0x4B;

        for (int i = 15; i < 45; i++) {
            t_ns[i] = 0x41;
        }

        t_ns[45] = 0x00;
        t_ns[46] = 0x00;
        t_ns[47] = 0x21;
        t_ns[48] = 0x00;
        t_ns[49] = 0x01;
        return t_ns;
    }

    // 表1 “UDP-NetBIOS-NS”应答包的结构及主要字段一览表
    // 序号字段名长度
    // 1 Transaction ID 两字节(16位)
    // 2 Flags 两字节(16位)
    // 3 Questions 两字节(16位)
    // 4 AnswerRRs 两字节(16位)
    // 5 AuthorityRRs 两字节(16位)
    // 6 AdditionalRRs 两字节(16位)
    // 7 Name<Workstation/Redirector> 34字节(272位)
    // 8 Type:NBSTAT 两字节(16位)
    // 9 Class:INET 两字节(16位)
    // 10 Time To Live 四字节(32位)
    // 11 Length 两字节(16位)
    // 12 Number of name 一个字节(8位)
    // NetBIOS Name Info 18×Number Of Name字节
    // Unit ID 6字节(48位

    protected final String GetMacAddr(byte[] brevdata) throws Exception {
        // 获取计算机名
        System.out.println(new String(brevdata, 57, 18));
        System.out.println(new String(brevdata, 75, 18));
        System.out.println(new String(brevdata, 93, 18));
        int i = brevdata[56] * 18 + 56;
        String sAddr = "";
        StringBuffer sb = new StringBuffer(17);
        // 先从第56字节位置,读出Number Of Names(NetBIOS名字的个数,其中每个NetBIOS Names Info部分占18个字节)
        // 然后可计算出“Unit ID”字段的位置=56+Number Of Names×18,最后从该位置起连续读取6个字节,就是目的主机的MAC地址。
        for (int j = 1; j < 7; j++) {
            sAddr = Integer.toHexString(0xFF & brevdata[i + j]);
            if (sAddr.length() < 2) {
                sb.append(0);
            }
            sb.append(sAddr.toUpperCase());
            if (j < 6) sb.append(':');
        }
        return sb.toString();
    }

    public final void close() {
        try {
            ds.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public final String GetRemoteMacAddr() throws Exception {
        byte[] bqcmd = GetQueryCmd();
        send(bqcmd);
        try{
        	DatagramPacket dp = receive();
        	String smac = GetMacAddr(dp.getData());
            close();
            return smac;
        }catch(java.net.SocketTimeoutException e){
        	close();
        	return "0x000000000000";
        }finally{
        	close();
        }
    }

    public static void main(String[] args) throws Exception {
        UdpGetClientMacAddr addr = new UdpGetClientMacAddr("10.182.129.195");
        System.out.println(addr.GetRemoteMacAddr());
    }
   
    /*// 获取真实IP的方法()
    public String getIpAddr(HttpServletRequest request) {
           String ip = request.getHeader("x-forwarded-for");
           if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
               ip = request.getHeader("Proxy-Client-IP");
           }
           if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
               ip = request.getHeader("WL-Proxy-Client-IP");
           }
           if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
               ip = request.getRemoteAddr();
           }
           return ip;
       }*/
}
 

 

总结一下,现在一般有3中方法获取mac地址

1.通过ActiveX的方法

2.通过在客户端运行ipconfig这类dos或者shell命令

3.就是前面那种通过发送udp包,得到应答后分析取mac地址

 

 

1.通过ActiveX的方法,这个的问题就是这能跑在ie这类浏览器上,而且客户如果不允许插件运行,那也获取不了,太依赖客户行为。获取mac代码,我懒得整理了,直接从http://hi.baidu.com/fangqm/blog/item/d3f7c5eae1c1ecdbd539c93f.html这里cp过来,

<HTML>
<HEAD>
     <TITLE>读取客户端MAC</TITLE>
     <META http-equiv=Content-Type c>
     <SCRIPT language=JScript event="OnCompleted(hResult,pErrorObject, pAsyncContext)" for=mac>
         document.forms[0].txtMACAddr.value = unescape(MACAddr); document.forms[0].txtIPAddr.value = unescape(IPAddr); document.forms[0].txtDNSName.value = unescape(sDNSName);
     </SCRIPT>
     <SCRIPT language=JScript event=OnObjectReady(objObject,objAsyncContext) for=mac>
         if (objObject.IPEnabled != null && objObject.IPEnabled != "undefined" && objObject.IPEnabled == true)
         {
             if (objObject.MACAddress != null && objObject.MACAddress != "undefined")
                 MACAddr = objObject.MACAddress;   //获取MAC地址
             if (objObject.IPEnabled && objObject.IPAddress(0) != null && objObject.IPAddress(0) != "undefined")
                 IPAddr = objObject.IPAddress(0); //获取IP地址
             if (objObject.DNSHostName != null && objObject.DNSHostName != "undefined")
                 sDNSName = objObject.DNSHostName;//获取计算机名
         }
     </SCRIPT>
     <META c name=GENERATOR>
</HEAD>
<BODY>
<OBJECT id=locator classid=CLSID:76A64158-CB41-11D1-8B02-00600806D9B6 VIEWASTEXT></OBJECT>
<OBJECT id=mac classid=CLSID:75718C9A-F029-11d1-A1AC-00C04FB6C223></OBJECT>
<SCRIPT language=JScript>
     var service = locator.ConnectServer();
     var MACAddr ;
     var IPAddr ;
     var DomainAddr;
     var sDNSName;
     service.Security_.ImpersonationLevel = 3;
     service.InstancesOfAsync(mac, 'Win32_NetworkAdapterConfiguration');
</SCRIPT>
<FORM id=formfoo name=formbar action=readMACAction.do method=post>
     <INPUT value="" name=txtMACAddr>
     <INPUT value="" name=txtIPAddr>
     <INPUT value="" name=txtDNSName>
</FORM>
</BODY>
</HTML> 

 

2.通过在客户端运行ipconfig这类dos或者shell命令,这个的缺点就是如果在客户机子不允许/不能运行该类命令或者客户修改了该类命令(如ipconfig修改为ipcon)。另外还有可能在运行命令的时候发生阻塞,这个时候你就不知道什么时候能获取mac了。

 

获取方法还是懒得自己再写了,从http://blog.163.com/09zzy@126/blog/static/71197665201001504753750/拷贝过来

 

 

 import java.io.BufferedReader;   
 import java.io.IOException;   
 import java.io.InputStreamReader;   
   
 /**  
  * 获取MAC地址  
  * @author sunlightcs  
  *  
  */  
 public class GetMacAddress {   
   
       /**   
        *  获取当前操作系统名称.   
        *  return 操作系统名称 例如:windows,Linux,Unix等.   
       */     
      public static String getOSName() {     
          return System.getProperty("os.name").toLowerCase();     
      }     
               
      /**   
        * 获取Unix网卡的mac地址.   
       * @return mac地址   
       */     
      public static String getUnixMACAddress() {     
          String mac = null;     
          BufferedReader bufferedReader = null;     
          Process process = null;     
          try {     
                /**  
                 *  Unix下的命令,一般取eth0作为本地主网卡 显示信息中包含有mac地址信息    
                 */  
              process = Runtime.getRuntime().exec("ifconfig eth0");   
              bufferedReader = new BufferedReader(new InputStreamReader(process     
                      .getInputStream()));     
              String line = null;     
              int index = -1;     
              while ((line = bufferedReader.readLine()) != null) {     
                     /**  
                      *  寻找标示字符串[hwaddr]   
                      */  
                  index = line.toLowerCase().indexOf("hwaddr");    
                     /**  
                      * 找到了  
                      */  
                  if (index != -1) {     
                         /**  
                          *   取出mac地址并去除2边空格    
                          */  
                      mac = line.substring(index +"hwaddr".length()+ 1).trim();   
                      break;     
                  }     
              }     
          } catch (IOException e) {     
              e.printStackTrace();     
          } finally {     
              try {     
                  if (bufferedReader != null) {     
                      bufferedReader.close();     
                  }     
              } catch (IOException e1) {     
                 e1.printStackTrace();     
             }     
              bufferedReader = null;     
              process = null;     
          }     
       
          return mac;     
      }     
           
             
             
          /**   
            * 获取Linux网卡的mac地址.   
           * @return mac地址   
           */     
          public static String getLinuxMACAddress() {     
              String mac = null;     
              BufferedReader bufferedReader = null;     
              Process process = null;     
              try {     
                    /**  
                     *  linux下的命令,一般取eth0作为本地主网卡 显示信息中包含有mac地址信息    
                     */  
                  process = Runtime.getRuntime().exec("ifconfig eth0");   
                  bufferedReader = new BufferedReader(new InputStreamReader(process     
                          .getInputStream()));     
                  String line = null;     
                  int index = -1;     
                  while ((line = bufferedReader.readLine()) != null) {     
                      index = line.toLowerCase().indexOf("硬件地址");    
                         /**  
                          * 找到了  
                          */  
                      if (index != -1) {     
                             /**  
                              *   取出mac地址并去除2边空格    
                              */  
                          mac = line.substring(index+4).trim();   
                          break;     
                      }     
                  }     
              } catch (IOException e) {     
                  e.printStackTrace();     
              } finally {     
                  try {     
                      if (bufferedReader != null) {     
                          bufferedReader.close();     
                      }     
                  } catch (IOException e1) {     
                     e1.printStackTrace();     
                 }     
                  bufferedReader = null;     
                  process = null;     
              }   
           
              return mac;     
          }   
             
          /**   
           * 获取widnows网卡的mac地址.   
           * @return mac地址   
           */     
          public static String getWindowsMACAddress() {     
              String mac = null;     
              BufferedReader bufferedReader = null;     
              Process process = null;     
              try {     
                    /**  
                     * windows下的命令,显示信息中包含有mac地址信息    
                     */  
                  process = Runtime.getRuntime().exec("ipconfig /all");   
                  bufferedReader = new BufferedReader(new InputStreamReader(process     
                          .getInputStream()));     
                  String line = null;     
                  int index = -1;     
                  while ((line = bufferedReader.readLine()) != null) {     
                         /**  
                          *  寻找标示字符串[physical address]   
                          */  
                      index = line.toLowerCase().indexOf("physical address");    
                      if (index != -1) {   
                          index = line.indexOf(":");   
                          if (index != -1) {   
                                 /**  
                                  *   取出mac地址并去除2边空格  
                                  */  
                             mac = line.substring(index + 1).trim();    
                         }   
                          break;     
                      }   
                  }   
              } catch (IOException e) {     
                  e.printStackTrace();     
              }finally {     
                  try {     
                      if (bufferedReader != null) {     
                          bufferedReader.close();     
                        }     
                  }catch (IOException e1) {     
                      e1.printStackTrace();     
                    }     
                  bufferedReader = null;     
                  process = null;     
              }     
           
              return mac;     
          }     
           
          /**   
           * 测试用的main方法.   
           *    
           * @param argc   
          *            运行参数.   
           */     
          public static void main(String[] argc) {     
              String os = getOSName();     
              System.out.println(os);     
              if(os.startsWith("windows")){     
                  String mac = getWindowsMACAddress();     
                  System.out.println("本地是windows:"+mac);     
              }else if(os.startsWith("linux")){     
                    String mac = getLinuxMACAddress();     
                  System.out.println("本地是Linux系统,MAC地址是:"+mac);   
              }else{     
                  String mac = getUnixMACAddress();                         
                  System.out.println("本地是Unix系统 MAC地址是:"+mac);   
              }     
          }     
   
 }  
 

3.就是前面那种通过发送udp包,得到应答后分析取mac地址。缺点,首先你要获取准确的客户ip,并且客户机开发了netbios服务和137端口。

 

 

分享到:
评论

相关推荐

    JAVA外文文献+翻译.doc

    CGI程序的响应取决于发送的数据量,以及服务器和客户机的负载。 Java的优点 Java的出现解决了这个问题。Java是一种面向对象的编程语言,可以在客户机上运行小程序,称为Applet。Applet可以完成复杂的交互式任务...

    MAC加密算法(银联标准)

    数据不为8的倍数,需要补0,将数据8个字节进行异或,再将异或的结果与下一个8个字节异或,一直到最后,将异或后的数据进行DES计算。...我当时遇到了客户要求加mac算法,但是在网上搜索,没有银联标准的。所以就。

    基于java的局域网聊天系统-毕业设计.doc

    编程语言:java 硬件平台 CPU:Pentium4以上 内存:128M以上 软件平台 操作系统:windows系列,mac系列,linux等 开发工具: Eclipse,JDK6 描述: (1)实现群聊和私聊; (2)实现文件的发送与接收; (3)实现截图功能...

    《客户》.款经典的MySQL客户端软件.pdf

    虽然有针对Mac和Linux的Java版本jHeidi,但该项目已被停止。 6. **phpMyAdmin**:这是一款使用PHP编写的Web界面工具,可在线管理MySQL数据库。它支持广泛的操作,如数据库和表管理、用户权限设置,以及直接执行SQL...

    java源码管理系统-Simple-Company-Management-with-Database-:简单易用的桌面程序可在许多操作系统(W

    这个系统具有跨平台性,可以在多种操作系统上运行,包括Windows、Linux和Mac OS等。它提供了一种简单且用户友好的界面,使企业能够高效地管理其日常运营数据。 【描述】中的"java源码管理系统"表明这是一个使用Java...

    华为面试常见问题

    - **交换机**:工作在数据链路层,通过MAC地址表进行数据帧的转发。 - **路由器**:工作在网络层,使用IP地址和路由表来决定数据包的最佳路径。 **4. C++中的类与C语言中的struct的区别** - **C++中的类**:支持...

    工厂模式测试代码

    这种设计模式的主要目的是将对象的创建过程封装起来,使得代码更加灵活,易于扩展,并且能够解耦客户代码与具体实现。 首先,我们来看“工厂模式”。在工厂模式中,我们定义一个创建对象的接口,但让子类决定实例化...

    mockups安装程序、注册机及站点提供的例子

    "mockups安装程序"指的是Mockups的安装文件,可能是.exe或.dmg格式,取决于操作系统(Windows或Mac)。安装程序会引导用户完成软件的下载和安装过程,包括接受许可协议、选择安装位置、配置设置等步骤。安装完成后,...

    网管教程 从入门到精通软件篇.txt

    Axx:ARJ压缩文件的分包序号文件,用于将一个大文件压至几个小的压缩包中(xx取01-99的数字) A3L:Authorware 3.x库文件 A4L:Authorware 4.x库文件 A5L:Authorware 5.x库文件 A3M,A4M:Authorware Macintosh...

Global site tag (gtag.js) - Google Analytics