java怎样取得网卡物理地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java怎样取得网卡物理地址相关的知识,希望对你有一定的参考价值。

给你一个局域网的聊天程序或许对你有用!!!
import java.net.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.GregorianCalendar;
import javax.swing.JDialog;

public class QQ extends Frame implements ActionListener
Label label1 = new Label("请输入您要发送的信息(限英文):");
Label label2 = new Label("以下是你收到的消息记录:");
Label label3 = new Label("把以上消息发给如下IP地址:");
TextArea input = new TextArea("", 7, 14, TextArea.SCROLLBARS_BOTH);
TextArea output = new TextArea("", 8, 14, TextArea.SCROLLBARS_BOTH);
TextField IPAdd = new TextField("192.168.1.88");
Button send = new Button("发送消息");
Button about = new Button("关于");
Button clear = new Button("清空消息纪录");
GregorianCalendar time = new GregorianCalendar();

QQ()
super("仿QQ聊天工具");
setLayout(null);
setLocation(250, 250);
this.setSize(518, 218);
this.setResizable(false); // 大小不可变
this.setBackground(new Color(220, 220, 220));
Toolkit kit = Toolkit.getDefaultToolkit();
Image myImage = kit.getImage("icons\\\\QQ.bmp");
this.setIconImage(myImage);

label1.setFont(new Font("宋体", Font.PLAIN, 12));
label1.setForeground(new Color(0, 0, 192));
label1.setBounds(8, 28, 216, 16);

input.setBackground(new Color(255, 255, 128));
input.setFont(new Font("Times New Roman", Font.BOLD, 15));
input.setForeground(Color.magenta);
input.setBounds(8, 44, 248, 120);

output.setBackground(new Color(128, 255, 255));
output.setFont(new Font("Times New Roman", Font.PLAIN, 12));
output.setForeground(Color.magenta);
output.setBounds(264, 44, 248, 136);
output.setEditable(false);

send.setFont(new Font("新宋体", Font.PLAIN, 12));
send.setLocation(136, 188);
send.setSize(120, 22);

clear.setFont(new Font("新宋体", Font.PLAIN, 12));
clear.setLocation(392, 188);
clear.setSize(120, 22);

label2.setFont(new Font("宋体", Font.PLAIN, 12));
label2.setForeground(new Color(0, 0, 192));
label2.setBounds(264, 28, 216, 16);

about.setFont(new Font("新宋体", Font.PLAIN, 12));
about.setLocation(264, 188);
about.setSize(120, 22);

label3.setFont(new Font("宋体", Font.PLAIN, 12));
label3.setForeground(new Color(0, 0, 192));
label3.setBounds(8, 172, 160, 16);

IPAdd.setFont(new Font("新宋体", Font.PLAIN, 12));
IPAdd.setLocation(8, 190);
IPAdd.setSize(120, 19);

add(label1);
add(input);
add(label3);
add(label2);
add(output);
add(IPAdd);
add(send);
add(about);
add(clear);
addWindowListener(new closeWin());
send.addActionListener(this);
about.addActionListener(this);
clear.addActionListener(this);

setVisible(true);
waitForData();


public void actionPerformed(ActionEvent e)
if (e.getSource() == send)
sendData();
else if (e.getSource() == clear)
output.setText("");
else if (e.getSource() == about)
AboutQQ test = new AboutQQ(this);



public static void main(String args[])
new QQ();


void sendData()
try
String msg = input.getText();
if (msg.equals(""))
return ;
input.setText("");
String ad = IPAdd.getText();
InetAddress tea = InetAddress.getLocalHost();
String asd = tea.getHostAddress();//发送方的IP地址
output.append("[" + asd + "]:(" + time.get(GregorianCalendar.YEAR)
+ "-" + time.get(GregorianCalendar.MONTH) + "-"
+ time.get(GregorianCalendar.DATE) + " "
+ time.get(GregorianCalendar.HOUR) + ":"
+ time.get(GregorianCalendar.MINUTE) + ":"
+ time.get(GregorianCalendar.SECOND) + ") " + "\\n" + msg
+ "\\n");
msg = "From [" + asd + "]:(" + time.get(GregorianCalendar.YEAR)
+ "-" + time.get(GregorianCalendar.MONTH) + "-"
+ time.get(GregorianCalendar.DATE) + " "
+ time.get(GregorianCalendar.HOUR) + ":"
+ time.get(GregorianCalendar.MINUTE) + ":"
+ time.get(GregorianCalendar.SECOND) + ") \\n" + msg;
InetAddress address = InetAddress.getByName(ad);
int len = msg.length();
byte[] message = new byte[len];
msg.getBytes(0, len, message, 0);
DatagramPacket packet = new DatagramPacket(message, len, address,
9999);
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
catch (Exception e)



void waitForData()
try
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
DatagramSocket socket = new DatagramSocket(9999);
while (true)
socket.receive(packet);
String s = new String(buffer, 0, 0, packet.getLength());
output.append(s + "\\n");
packet = new DatagramPacket(buffer, buffer.length);

catch (Exception e)




class closeWin extends WindowAdapter
public void windowClosing(WindowEvent e)
Frame fr = (Frame) (e.getSource());
fr.dispose();
System.exit(0);



class AboutQQ
private Label label;
private JDialog dialog;

public AboutQQ(Frame f)
label = new Label("Version 1.0");
dialog = new JDialog(f, "About", true);
dialog.setLocation(f.getLocation());
Container dialogPane = dialog.getContentPane();
dialogPane.setLayout(new BorderLayout());
dialogPane.add(label);
dialogPane.setBounds(50,50,50,50);
dialog.pack();
dialog.setVisible(true);

参考技术A InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
byte[] mac = network.getHardwareAddress();
System.out.print("Current MAC address : ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++)
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));

System.out.println(sb.toString());

试试,应该是有效的

如何确定实际物理网卡的 MAC 地址——不是由 *** (.NET C#) 创建的虚拟网络接口

【中文标题】如何确定实际物理网卡的 MAC 地址——不是由 *** (.NET C#) 创建的虚拟网络接口【英文标题】:How to determine MAC Address of the actual physical network card -- not virtual network interfaces created by ***'s (.NET C#) 【发布时间】:2010-12-06 17:53:51 【问题描述】:

背景

我正在尝试从计算机中获取唯一标识符,并希望每次都能可靠地返回相同的 MAC 地址。相信我,我有使用 MAC 地址的理由,并且阅读了许多关于替代唯一 ID 方法的帖子(是的,我考虑过他们是否没有任何网卡)。

问题

问题出在 .NET 中,我看不出特定的 NetworkInterface 是否是来自诸如“Nortel IPSECSHM Adapter - Packet Scheduler Miniport”之类的物理硬件网卡,当您连接到某些 *** 或WiFi 网络。

我知道如何使用类似下面的代码获取 Mac 地址:

    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    
        log.Debug("NIC " + nic.OperationalStatus + " " + nic.NetworkInterfaceType + " " + nic.Speed + " " + nic.GetPhysicalAddress() + " " + nic.Description);
    

可以理解,没有 100% 的方法来确保我会获得内部网卡,但 我想选择 MAC 地址以返回给定机器最不可能更改的 MAC 地址强>。与诸如是否连接到 wifi...等因素无关...通过某种类型的系绳连接...或者他们安装了一些新的 *** 软件来添加新界面。

考虑的策略

1) 选择“Up”的第一个界面。这在我的笔记本电脑上失败了,因为“数据包微型端口”始终处于启动状态。此外,如果我将手机连接到笔记本电脑,这也会显示为第一张卡。

2) 选择最合适的类型...这失败了 b/c 基本上所有东西都显示为“以太网”,包括 WiFi 适配器和我的 iPHone 网络共享互联网连接。

3) 选择具有 IP 地址的 NIC。失败有几个原因:1)网卡可能没有连接到 LAN 2)有多个网卡可能有 IP 地址。

4) 只需发送所有 MAC 地址...问题是列表会根据安装的软件而变化,并且很难比较。

5) 选择速度最快的mac地址。我想这可能是我最好的选择。我认为可以肯定地说,最快的界面通常是最永久的。

或者,在 .NET 中可能有其他方法可以检测物理卡,或者如果您可以推荐一种可以提供不同信息的 API 调用,我会考虑调用其他 API。

还有其他想法吗?

在这里演示的是我的 iphone 系留时上面示例代码的输出:

DEBUG - NIC Down Ethernet 500000     0021E98BFBEF Apple Mobile Device Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up   Ethernet 10000000   444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000   00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up   Loopback 10000000  MS TCP Loopback interface

没有连接 Iphone:

DEBUG - NIC Up   Ethernet 10000000   444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000   00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up   Loopback 10000000  MS TCP Loopback interface

【问题讨论】:

您还应该考虑具有多个相同类型 NIC 的计算机。 您不能依赖 MAC 地址作为唯一标识符。如果您想要一个唯一标识符,请生成一个 GUID,对其进行加密并将其存储在计算机上。 @John Saunders,我确实使用 GUID。 MAC 地址是一个备份,以防 GUID 的存储位置被删除。 查看我的回答***.com/a/40088578/1498252 以检查物理设备。 【参考方案1】:

这是我的方法: 它利用物理卡连接到PCI接口的事实

ManagementObjectSearcher searcher = new ManagementObjectSearcher
    ("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND PNPDeviceID IS NOT NULL");
ManagementObjectCollection mObject = searcher.Get();

foreach (ManagementObject obj in mObject)

    string pnp = obj["PNPDeviceID"].ToString();
    if (pnp.Contains("PCI\\"))
    
        string mac = obj["MACAddress"].ToString();
        mac = mac.Replace(":", string.Empty);
        return mac;
    

【讨论】:

我不认为这会满足这样的需求:amazon.co.uk/Belkin-Ethernet-Adapter-Patch-Cable/dp/B0002AFKN0 - 但是它们并不是那么普遍。 是的,这是个问题。我没有这样的设备,有趣的是,在这种情况下,“PNPDeviceID”中写的是什么。第二个问题是当有不止一张卡时。因为我总是取“第一张”牌,所以在“选择”运算符中的牌顺序不确定的情况下可能会导致错误。我没有在这个“SQL for WMI”方言中找到“order by”结构:) 我有一个适配器,其标题为“Broadcom BCM5709C NetXtreme II GigE(NDIS VBD 客户端)”和没有“PCI\”的 PNPDeviceID。它是物理的。 如何获取物理适配器的 IPv4 地址? (远程计算机) PhysicalAdapter ?网络适​​配器属性名称:NetEnabled - 值:True 网络适配器属性名称:PhysicalAdapter - 值:True 网络适配器属性名称:PNPDeviceID -值:PCI\VEN_15AD&DE【参考方案2】:

MAC 地址的前三个字节是制造商 ID。您可以将某些已知不适合您的制造商 ID 列入黑名单,并忽略这些接口。

依赖速度可能不是一个好主意,因为 *** 接口没有理由不能报告自己具有千兆速度。

【讨论】:

我考虑过列入黑名单...我认为根据描述中出现的字符串(例如:“***”、“IPSECSHM”...但是认为这很难想出。或者,我想我可以创建一个最流行的网络接口的白名单......“Realtek”,“Gigabit” - 我真的想避免创建和维护一个白名单。【参考方案3】:

MAC 地址是物理硬件地址。我无法在这台电脑上进行测试,但我认为如果添加虚拟连接,您将不会获得新的 MAC 地址,因为它不是实际的硬件。这将是另一个连接,但不是另一个 MAC 地址。

因此,确保您每次都获得相同的 MAC 地址取决于连接到机器的相同硬件,并且您使用相同的算法从该硬件中进行选择。

【讨论】:

@Brian - MAC 地址也用于虚拟接口......在我的例子中是 Nortel Packet 接口。【参考方案4】:

我也一直在研究这个问题,并且相信如果没有持久状态,就很难维持稳定的 MAC。

我正在玩弄的解决方案是获取在适配器顺序中找到的第一个 NIC,然后使用它并保存它。然后在后续的 UUID 生成中,如果在堆栈中的任何位置找到保存的 MAC,即使不是第一个,也要使用它。这样适配器订单可以移动,我们不用担心会炸毁任何依赖于稳定 MAC(例如许可模块)的东西。

如果在堆栈中找不到保存的 MAC,则将其丢弃,我们只需使用绑定顺序中的第一个 MAC 并重新开始。

【讨论】:

【参考方案5】:
 public static string GetMacAddressPhysicalNetworkInterface()
    

        ManagementObjectSearcher searcher = new ManagementObjectSearcher
        ("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND" +
         " PNPDeviceID IS NOT NULL AND" +
         " PhysicalAdapter = true");
        ManagementObjectCollection mObject = searcher.Get();

        string macs = (from ManagementObject obj in mObject
                let pnp = obj["PNPDeviceID"].ToString()
                where !(pnp.Contains("ROOT\\"))
                //where  pnp.Contains("PCI\\")  || pnp.Contains("USB\\")
                select obj).Select(obj => obj["MACAddress"].ToString())
            .Aggregate<string, string>(null, (mac, currentMac) => mac + currentMac.Replace(":", string.Empty) + ",");

        return !string.IsNullOrEmpty(macs) ? macs.Substring(0, macs.Length - 1) : macs;
    

    public static NetworkInterface GetPhysicalNetworkInterface(string macAddressPhysicalNetworkInterface)
    
        return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(currentNetworkInterface => string.Equals(currentNetworkInterface.GetPhysicalAddress().ToString(), macAddressPhysicalNetworkInterface, StringComparison.CurrentCultureIgnoreCase));
    

【讨论】:

一些解释/文档链接解释了为什么这个答案比其他答案更好会有所帮助。我确实喜欢“physicaladapter = true”检查,但可以依赖它吗? 勾选这个属性也够了 如何使用scope = "\\\\" + ip + "\\root\\cimv2";获取GetPhysicalNetworkInterface

以上是关于java怎样取得网卡物理地址的主要内容,如果未能解决你的问题,请参考以下文章

怎样改变eth0,eth1,eth2,eth3所对应的物理网卡

电脑网卡MAC地址的更改

Oracle VM VirtualBox虚拟机,如何设定使用物理网卡和物理网卡设定的IP地址

网卡地址 MAC格式是啥样的?

电脑主板更换后,物理地址会发生改变么?

Linux上的物理网卡与虚拟网络设备