- 首先说,多数时候你并不会遇到SNMP中文问题
目前有可能遇到的中文SNMP问题的场景:
1. 一些国产网络设备(别提华为,华为路由器的多数网管信息也是西文的)
2. Windows平台的SNMP服务
3. 一些国产网管软件
- SNMP4J处理中文时的问题:当遇到中文或者编码值大于 0x80 的字符时,就会直接以十六机制数输出
|
执行代码: 1.3.6.1.2.1.2.2.1.2.1:4d:53:20:54:43:50:20:4c:6f:6f:70:62:61:63:6b:20:69:6e:74:65:72:66:61:63:65:00 OCTET STRING 1.3.6.1.2.1.2.2.1.2.2:56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:38:00 OCTET STRING 1.3.6.1.2.1.2.2.1.2.3:56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:31:00 OCTET STRING 1.3.6.1.2.1.2.2.1.2.4:52:65:61:6c:74:65:6b:20:52:54:4c:38:31:33:39:20:46:61:6d:69:6c:79:20:50:43:49:20:46:61:73:74:20:45:74:68:65:72:6e:65:74:20:4e:49:43:20:2d:20:ca:fd:be:dd:b0:fc:bc:c6:bb:ae:b3:cc:d0:f2:ce:a2:d0:cd:b6:cb:bf:da:00 OCTET STRING 1.3.6.1.2.1.2.2.1.2.65542:41:53:55:53:20:38:30:32:2e:31:31:62:2f:67:20:57:69:72:65:6c:65:73:73:20:4c:41:4e:20:43:61:72:64:20:2d:20:ca:fd:be:dd:b0:fc:bc:c6:bb:ae:b3:cc:d0:f2:ce:a2:d0:cd:b6:cb:bf:da:00 OCTET STRING |
- 原因:问题出在SNMP4J的基础字符串类OctetString上。
问题出在OctetString类的toString方法:
public class OctetString extends AbstractVariable |
|
- 解决法1:网上有人给的建议是直接把OctetString类里toString方法里的if (isPrintable())部分取消掉,就是用基本的String转换
|
1.3.6.1.2.1.2.2.1.2.1:MS TCP Loopback interface OCTET STRING 1.3.6.1.2.1.2.2.1.2.2:VMware Virtual Ethernet Adapter for VMnet8 OCTET STRING 1.3.6.1.2.1.2.2.1.2.3:VMware Virtual Ethernet Adapter for VMnet1 OCTET STRING 1.3.6.1.2.1.2.2.1.2.4:Realtek RTL8139 Family PCI Fast Ethernet NIC - 数据包计划程序微型端口 OCTET STRING 1.3.6.1.2.1.2.2.1.2.65542:ASUS 802.11b/g Wireless LAN Card - 数据包计划程序微型端口 OCTET STRING |
这种方法更不可取,因为isPrintable()方法是用于判断可显示字符的,其中 不止判断大于0x80,还有包括控制字符的判断(0-31,127-159)
(codePoint >= 0x0000 && codePoint <= 0x001F) || (codePoint >= 0x007F && codePoint <= 0x009F);
- 解决法2:克服法1的缺陷,toString()不变,只修改isPrintable()
public String toString() { |
|
注意: 上面codePoint变量的操作,基本就是Character.isISOControl(c)的操作
- 解决法3:在国外的论坛上,有的比较死板的人要求按正规的“继承+覆写方法”的方式做修改,这样能保证源码的不被改变
既然是开源的代码,该修改就修改.
解决法修改后,获取mac地址有问题,出现乱码。最好在出现中文的地方调用此方法:
public static String getChinese(String octetString) { //snmp4j遇到中文直接转成16进制字符串
try {
String[] temps = octetString.split(":");
byte[] bs = new byte[temps.length];
for (int i = 0; i < temps.length; i++)
bs[i] = (byte) Integer.parseInt(temps[i], 16);
return new String(bs, "GB2312");
} catch (Exception e) {
return null;
}
}