SNMP:“简单网络管理协议”,用于网络管理的协议。SNMP用于网络设备的管理。SNMP的工作方式:管理员需要向设备获取数据,所以SNMP提供了get操作;管理员需要向设备执行设置操作,所以SNMP提供了set操作;设备需要在重要状况改变的时候,向管理员通报事件的发生,所以SNMP提供了Trap操作。

1)操作命令
SNMP协议之所以易于使用,这是因为它对外提供了三种用于控制MIB对象的基本操作命令。它们是:Get、Set 和 Trap。
Get:管理站读取代理者处对象的值。它是SNMP协议中使用率最高的一个命令,因为该命令是从网络设备中获得管理信息的基本方式。
Set:管理站设置代理者处对象的值
Trap: 代理者主动向管理站通报重要事件。Trap 消息可以用来通知管理站线路的故障、连接的终端和恢复、认证失败等消息。管理站可相应的作出处理。使用指南

2)SNMP的消息构成
一条snmp消息由版本识别符、团体名、PDU组成:
1. 版本识别符:用于说明现在使用的是哪个版本的SNMP协议,确保SNMP代理使用相同的协议,每个SNMP代理都直接抛弃与自己协议版本不同的数据报。
2. 团体名:团体是基本的安全机制,用于实现SNMP网络管理员访问SNMP管理代理时的身份验证。类似于密码,默认值为 public。
3. 协议数据单元(PDU):PDU (协议数据单元)是SNMP消息中的数据区, 即Snmp通信时报文数据的载体。PDU指明了SNMP的消息类型及其相关参数

3)MIB与OID
1.MIB(管理信息库)
  管理信息(MIB)库可以理解成为agent维护的管理对象数据库, MIB数据对象以一种树状分层结构进行组织,这个树状结构中的每个分枝都有一个专用的名字和一个数字形式的标识符。使用这个树状分层结构,MIB浏览器能够以一种方便而且简洁的方式访问整个MIB数据库。可以通过其数字标识符来查找MIB中的数据对象,这个数字标识符号从结构树的顶部(或根部)开始,直到各个叶 子节点(即数据对象)为止。
  每一个节点都有一个对象标识符(OID)来唯一的标识,每个节点用数字和字符两种方式显示,其中对象标识符OID是由句点隔开的一组整数,也就是从根节点 通向它的路径。一个带标号节点可以拥有包含其它带标号节点为它的子树,如果没有子树它就是叶子节点,它包含一个值并被称为对象。比如网络设备名的oid 是.1.3.6.1.2.1.1.5.0,其值为设备名称的字符串。
2.OID(Object Identifier)
  每个管理对象都有自己的OID(Object Identifier),管理对象通过树状结构进行组织,OID由树上的一系列整数组成,整数之间用点( . )分隔开,树的叶子节点才是真正能够被管理的对象。

1.2 主要代码分析
这该模块对snmp的get、walk、trap三种方式的业务处理进行介绍。
执行过程概述
驻留在被管设备上的AGENT从UDP端口161接受来自网管站的串行化报文,经解码、团体名验证、分析得到管理变量在MIB树中对应的节点,从相应的模块中得到管理变量的值,再形成响应报文,编码发送回网管站。网管站得到响应报文后,再经同样的处理,最终显示结果。下面根据RFC1157详细介绍Agent接受到报文后采取的动作:首先解码生成用内部数据结构表示的报文,解码依据ASN.1的基本编码规则,如果在此过程中出现错误导致解码失败则丢弃该报文,不做进一步处理。第二步:将报文中的版本号取出,如果与本Agent支持的SNMP版本不一致,则丢弃该报文,不做进一步处理。当前北研的数据通信产品只支持SNMP版本1。第三步:将报文中的团体名取出,此团体名由发出请求的网管站填写。如与本设备认可的团体名不符,则丢弃该报文,不做进一步处理,同时产生一个陷阱报文。SNMPv1只提供了较弱的安全措施,在版本3中这一功能将大大加强。第四步:从通过验证的ASN.1对象中提出协议数据单元PDU,如果失败,丢弃报文,不做进一不处理。否则处理PDU,结果将产生一个报文,该报文的发送目的地址应同收到报文的源地址一致。根据不同的PDU,SNMP协议实体将做不同的处理

常见问题:

1.使用get方式请求获取信息,一直返回 noSuchObject说明没有找到该节点,需要确定该oid是否正确。若没有返回说明连接不正常,需要检查各个版本、用户名、密码、协议、团体名等配置信息是否正确。
2. 创建目标对象时,使用v1、v2版本时需要指定团体名,使用v3需要指定安全名。
3.配置v3用户时,最好通过管理口进行配置,web页面配置可能不生效。
4.使用get方式请求获取信息,返回的数据为null,说明oid有错误的,错误的oid后面的返回oid都会为null,需要把错误的oid改正确。(亲身经历过)​​​​​​​

5、通过snmp协议批量请求oid时,会遇到部分设备返回oid信息为空

排查日志后,发现是返回的response为空,但抓包发现response是有值的,而且会重复请求,同一个oid的请求时间和响应时间相差30s左右,然后通过ping命令发现有丢包问题,分析下来是网络问题,于是就调大snmp连接超时时间(亲身经历过)

​​​​​​​

ResponseEvent responseEvent = snmp.send(pdu, target);
PDU response = responseEvent.getResponse();
CommunityTarget target = new CommunityTarget();
target.setTimeout(60000);

walk方式获取数据:

 public class MultiThreadedWalkDemo {private static final Logger LOGGER = LogManager.getLogger(MultiThreadedWalkDemo.class);
//用户名private String username = "nms2-admin";//鉴权密码private String authPassword = "hello123";//数据加密密码private String privPassword = "hello123";//trap地址private String address = "udp:192.160.0.1/162";//get 地址private String addressGet = "udp:192.160.0.2/161";public MultiThreadedWalkDemo() {}public void  initSnmp() throws IOException {//1、初始化多线程消息转发类MessageDispatcher messageDispatcher = new MessageDispatcherImpl();//其中要增加三种处理模型。如果snmp初始化使用的是Snmp(TransportMapping<? extends Address> transportMapping) ,就不需要增加messageDispatcher.addMessageProcessingModel(new MPv1());messageDispatcher.addMessageProcessingModel(new MPv2c());//当要支持snmpV3版本时,需要配置userOctetString localEngineID = new OctetString(MPv3.createLocalEngineID());USM usm = new USM(SecurityProtocols.getInstance().addDefaultProtocols(), localEngineID, 0);OctetString userName1 = new OctetString(username);OctetString authPass = new OctetString(authPassword);OctetString privPass = new OctetString(privPassword);UsmUser user = new UsmUser(userName1, AuthMD5.ID, authPass, PrivAES128.ID, privPass);usm.addUser(user.getSecurityName(), user);messageDispatcher.addMessageProcessingModel(new MPv3(usm));//2、创建transportMapping  ip为本地ip,可以不设置//UdpAddress updAddr = (UdpAddress) GenericAddress.parse("udp:192.168.22.100/161");TransportMapping<?> transportMapping = new DefaultUdpTransportMapping();//3、正式创建snmpsnmp = new Snmp(messageDispatcher, transportMapping);//开启监听snmp.listen();}private  Target createTarget(String oid) {Target target = null;int version = 1;if (!(version == SnmpConstants.version3 || version == SnmpConstants.version2c || version == SnmpConstants.version1)) {//log.error("参数version异常");return target;}if (version == SnmpConstants.version3) {target = new UserTarget();//snmpV3需要设置安全级别和安全名称,其中安全名称是创建snmp指定user设置的new OctetString("SNMPV3")target.setSecurityLevel(SecurityLevel.AUTH_PRIV);target.setSecurityName(new OctetString(this.username));} else {//snmpV1和snmpV2需要指定团体名名称target = new CommunityTarget();((CommunityTarget) target).setCommunity(new OctetString(this.username));if (version == SnmpConstants.version2c) {target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);}}target.setVersion(version);//必须指定,没有设置就会报错。target.setAddress(GenericAddress.parse(this.addressGet));target.setRetries(3);target.setTimeout(2000);return target;}private static PDU createPDU(int version, int type, String oid) {PDU pdu = null;if (version == SnmpConstants.version3) {pdu = new ScopedPDU();} else {pdu = new PDUv1();}pdu.setType(type);//可以添加多个变量oid/*for(String oid:oids){pdu.add(new VariableBinding(new OID(oid)));}*/pdu.add(new VariableBinding(new OID(oid)));return pdu;}/*** WALK方式请求* @param oid*/public void snmpWalk(String oid) {try {LOGGER.info("walkfangshi");List<Map> list = new ArrayList<Map>();//1、初始化snmp,并开启监听initSnmp();//2、创建目标对象Target target = createTarget(oid);//3、创建报文PDU pdu = createPDU(1, PDU.GETNEXT, oid);//4、发送报文,并获取返回结果boolean matched = true;while (matched) {ResponseEvent responseEvent = snmp.send(pdu, target);if (responseEvent == null || responseEvent.getResponse() == null) {System.out.println("TimeOut...");break;}PDU response = responseEvent.getResponse();String nextOid = null;Vector<? extends VariableBinding> variableBindings = response.getVariableBindings();for (int i = 0; i < variableBindings.size(); i++) {Map map = new HashMap();VariableBinding variableBinding = variableBindings.elementAt(i);Variable variable = variableBinding.getVariable();nextOid = variableBinding.getOid().toDottedString();//如果不是这个节点下的oid则终止遍历,否则会输出很多,直到整个遍历完。if (!nextOid.startsWith(oid)) {matched = false;break;}map.put("oid", nextOid);map.put("value",variable);list.add(map);System.out.println("oid:" + nextOid + ",value:"  + variable);LOGGER.info("oid:" + nextOid + ",value:"  + variable);}if (!matched) {break;}pdu.clear();pdu.add(new VariableBinding(new OID(nextOid)));}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}//开启监控的main方法。public static void main(String[] args) throws IOException {MultiThreadedWalkDemo multithreadedtrapreceiver = new MultiThreadedWalkDemo();multithreadedtrapreceiver.run();}public void run() {try {LOGGER.info("开始监听walk信息!");LOGGER.info("开始获取端口名称!");String healthOID1 = "1.3.6.1.2.1.2.2.1.2";this.snmpWalk(healthOID1);LOGGER.info("网口流量");String healthOID2 = "1.3.6.1.2.1.2.2.1.10";this.snmpWalk(healthOID2);LOGGER.info("网口状态");String healthOID3 = "1.3.6.1.2.1.2.2.1.16";this.snmpWalk(healthOID3);LOGGER.info("网口速率");String healthOID4 = "1.3.6.1.2.1.31.1.1.1.15";this.snmpWalk(healthOID4);} catch (Exception ex) {ex.printStackTrace();}}
}

trap监听:

public class MultiThreadedTrapReceiverDemo implements CommandResponder {private static final Logger logger = LogManager.getLogger(MultiThreadedTrapReceiverDemo.class);//用户名private String username = "nms2-admin";//鉴权密码private String authPassword = "hello123";//数据加密密码private String privPassword = "hello123";//trap地址private String address = "udp:192.160.0.1/162";//get 地址private String addressGet = "udp:192.160.0.2/161";private MultiThreadedMessageDispatcher dispatcher;private Snmp snmp = null;private Address listenAddress;private ThreadPool threadPool;public MultiThreadedTrapReceiverDemo() {}private void init() throws UnknownHostException, IOException {try {//创建接收SnmpTrap的线程池,参数: 线程名称及线程数threadPool = ThreadPool.create("Trap", 2);//创建一个多线程消息分发器,以同时处理传入的消息,该实例将用于分派传入和传出的消息dispatcher = new MultiThreadedMessageDispatcher(threadPool,new MessageDispatcherImpl());//监听端的 ip地址 和 监听端口号listenAddress = GenericAddress.parse(address);//在指定的地址上创建UDP传输TransportMapping<?> transport;if (listenAddress instanceof UdpAddress) {//必须是本机地址transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);} else {transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);}//初始化snmp需要设置messageDispatcher里面的参数和TransportMapping参数snmp = new Snmp(dispatcher, transport);//消息分发器添加接收的版本信息/*      v1和v2都具有基本的读、写MIB功能。**      v2增加了警报、批量数据获取、管理站和管理站通信能力。**      v3在v2的基础上增加了USM,使用加密的数据和用户验证技术,提高了安全性*/snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());//创建具有所提供安全协议支持的USMUSM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3 //根据本地IP地址和其他四个随机字节创建本地引擎ID.createLocalEngineID()), 0);SecurityModels.getInstance().addSecurityModel(usm);// 添加安全协议,如果没有发过来的消息没有身份认证,可以跳过此段代码SecurityProtocols.getInstance().addDefaultProtocols();// 创建和添加用户OctetString userName1 = new OctetString(username);OctetString authPass = new OctetString(authPassword);OctetString privPass = new OctetString(privPassword);UsmUser usmUser1 = new UsmUser(userName1, AuthMD5.ID, authPass, PrivAES128.ID, privPass);//因为接受的Trap可能来自不同的主机,主机的Snmp v3加密认证密码都不一样,所以根据加密的名称,来添加认证信息UsmUser。//添加了加密认证信息的便可以接收来自发送端的信息。UsmUserEntry userEnty1 = new UsmUserEntry(userName1, usmUser1);UsmUserTable userTable = snmp.getUSM().getUserTable();// 添加其他用户userTable.addUser(userEnty1);//开启Snmp监听,可以接收来自Trap端的信息。snmp.listen();logger.info("开始监听trap告警");}catch (Exception e){e.printStackTrace();logger.info(e.getMessage());}}public void run() {try {init();snmp.addCommandResponder(this);System.out.println("开始监听Trap信息!");} catch (Exception ex) {ex.printStackTrace();}}/*** 实现CommandResponder的processPdu方法, 用于处理传入的请求、PDU等信息* 当接收到trap时,会自动进入这个方法** @param respEvnt*/public void processPdu(CommandResponderEvent respEvnt) {// 解析Responselogger.info("trap接受到告警消息,开始对消息进行处理");try {if (respEvnt != null && respEvnt.getPDU() != null) {RtEvent rtEvent = new RtEvent();for (int i = 0; i < respEvnt.getPDU().getVariableBindings().size(); i++) {logger.info("消息体oid:"+respEvnt.getPDU().getVariableBindings().elementAt(i).getOid());logger.info("消息体oid对应值:"+respEvnt.getPDU().getVariableBindings().elementAt(i).getVariable());}//获取对方交换机等设备的ipString ip = respEvnt.getPeerAddress().toString().split("/")[0].split(":")[0];rtEvent.setIp(ip);//获取设备以及trap信息DevAndTrapOid devAndTrapOid = ModelCache.getInstance().getDevAndTrapOid(ip);@SuppressWarnings("unchecked")Vector<VariableBinding> recVBs = (Vector<VariableBinding>) respEvnt.getPDU().getVariableBindings();for (int i = 0; i < recVBs.size(); i++) {VariableBinding recVB = recVBs.elementAt(i);String value = "点号" + recVB.getOid() + ";内容:" + recVB.getVariable();logger.info("二区trap初始snmp,点号:" + recVB.getOid() + ";内容:" + recVB.getVariable());System.out.println(value);}}}catch (Exception e){e.printStackTrace();}}//开启监控的main方法。public static void main(String[] args) throws IOException {MultiThreadedTrapReceiverDemo multithreadedtrapreceiver = new MultiThreadedTrapReceiverDemo();multithreadedtrapreceiver.run();}
}

get方式获取数据:

package com.snmp.collection.get_collection.collectionforII;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.*;public class MultiThreadedGetDemo {private static final Logger LOGGER = LogManager.getLogger(MultiThreadedGetDemo.class);//用户名private String username = "nms2-admin";//鉴权密码private String authPassword = "hello123";//数据加密密码private String privPassword = "hello123";//trap地址private String address = "udp:192.160.0.1/162";//get 地址private String addressGet = "udp:192.160.0.2/161";private MultiThreadedMessageDispatcher dispatcher;private Snmp snmp = null;private Address listenAddress;private ThreadPool threadPool;public MultiThreadedGetDemo() {}public void  initSnmp() throws IOException {//1、初始化多线程消息转发类MessageDispatcher messageDispatcher = new MessageDispatcherImpl();//其中要增加三种处理模型。如果snmp初始化使用的是Snmp(TransportMapping<? extends Address> transportMapping) ,就不需要增加messageDispatcher.addMessageProcessingModel(new MPv1());messageDispatcher.addMessageProcessingModel(new MPv2c());//当要支持snmpV3版本时,需要配置userOctetString localEngineID = new OctetString(MPv3.createLocalEngineID());USM usm = new USM(SecurityProtocols.getInstance().addDefaultProtocols(), localEngineID, 0);OctetString userName1 = new OctetString(username);OctetString authPass = new OctetString(authPassword);OctetString privPass = new OctetString(privPassword);UsmUser user = new UsmUser(userName1, AuthMD5.ID, authPass, PrivAES128.ID, privPass);usm.addUser(user.getSecurityName(), user);messageDispatcher.addMessageProcessingModel(new MPv3(usm));//2、创建transportMapping  ip为本地ip,可以不设置TransportMapping<?> transportMapping = new DefaultUdpTransportMapping();//3、正式创建snmpsnmp = new Snmp(messageDispatcher, transportMapping);//开启监听snmp.listen();}private  Target createTarget(String oid) {Target target = null;int version = 1;if (!(version == SnmpConstants.version3 || version == SnmpConstants.version2c || version == SnmpConstants.version1)) {//log.error("参数version异常");return target;}if (version == SnmpConstants.version3) {target = new UserTarget();//snmpV3需要设置安全级别和安全名称,其中安全名称是创建snmp指定user设置的new OctetString("SNMPV3")target.setSecurityLevel(SecurityLevel.AUTH_PRIV);target.setSecurityName(new OctetString(this.username));} else {//snmpV1和snmpV2需要指定团体名名称target = new CommunityTarget();((CommunityTarget) target).setCommunity(new OctetString(this.username));if (version == SnmpConstants.version2c) {target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);}}target.setVersion(version);//必须指定,没有设置就会报错。target.setAddress(GenericAddress.parse(this.addressGet));target.setRetries(3);target.setTimeout(2000);return target;}private static PDU createPDU(int version, int type, String oid) {PDU pdu = null;if (version == SnmpConstants.version3) {pdu = new ScopedPDU();} else {pdu = new PDUv1();}pdu.setType(type);//可以添加多个变量oid/*for(String oid:oids){pdu.add(new VariableBinding(new OID(oid)));}*/pdu.add(new VariableBinding(new OID(oid)));return pdu;}/*** GET方式请求* @param oid*/public  List<Map> snmpGet(String oid) {try {LOGGER.info("getfangshi");List<Map> list = new ArrayList<Map>();//1、初始化snmp,并开启监听initSnmp();//2、创建目标对象Target target = this.createTarget(oid);//3、创建报文PDU pdu = createPDU(1, PDU.GET, oid);//4、发送报文,并获取返回结果ResponseEvent responseEvent = snmp.send(pdu, target);PDU response = responseEvent.getResponse();if (response == null) {System.out.println("TimeOut...");} else {if (response.getErrorStatus() == PDU.noError) {//get方式获取到的返回值Vector<? extends VariableBinding> vbs = response.getVariableBindings();for (VariableBinding vb : vbs) {Map map = new HashMap();map.put("value",vb.getVariable());System.out.println("vb.getVariable():"  + vb.getVariable());System.out.println("OID:"  + vb.getVariable());LOGGER.info("OIDvALUE"  + vb.getVariable());list.add(map);}return list;} else {System.out.println("Error:" + response.getErrorStatusText());}}} catch (IOException e) {e.printStackTrace();}return null;}//开启监控的main方法。public static void main(String[] args) throws IOException {MultiThreadedGetDemo multithreadedtrapreceiver = new MultiThreadedGetDemo();multithreadedtrapreceiver.run();}public void run() {try {System.out.println("开始监听get信息!");LOGGER.info("内存");String devOid = "1.3.6.1.4.1.25506.2.6.1.1.1.1.8";this.snmpGet(devOid);LOGGER.info("cpu");String devOid1 = "1.3.6.1.4.1.25506.2.6.1.1.1.1.6";this.snmpGet(devOid1);LOGGER.info("运行时间");String data1 = "1.3.6.1.2.1.1.3.0";this.snmpGet(data1);} catch (Exception ex) {ex.printStackTrace();}}
}

snmp协议及常见问题分析相关推荐

  1. Modbus协议使用常见问题分析

    Modbus协议最初由Modicon公司开发出来,是针对PLC设备设计的基于串行总线的主从模式的应用层总线设备协议.ModbusTCP是封装在TCP包内的Modbus协议,虽然有一些变化,但是根本上还 ...

  2. SNMP协议的了解与简单的抓包分析

    文章目录 前言 一.SNMP是什么? 二.SNMP解读 1.实现结构 2.操作命令 3.SNMP报文 4 SNMP报文格式 三.SNMP抓包分析 1.SNMP体验 2.SNMP抓包分析 总结 前言 本 ...

  3. pda找不到服务器,PDA连不上服务器常见问题分析.doc

    PDA连不上服务器常见问题分析.doc PDA连不上服务器常见问题分析 请查看PDA的网络通不通,可以先检查WIFI/3G是否连接上网络,如果连接不上,点击PingToots工具,用"pin ...

  4. can总线配置读入是什么意思_STM32学习笔记—CAN总线收发数据常见问题分析

    CAN,Controller Area Network(控制器局域网络),在汽车电子.工业控制领域的应用比较多,通常用于局域组网. 这是第9篇学习分享文章,<STM32学习笔记>之CAN总 ...

  5. 微信小程序 RTMP 音视频 通话 ffmpeg_音视频常见问题分析和解决:HLS切片丢帧引起的视频卡顿问题排查...

    问题背景: 前两天看读者留言让再写写音视频问题排查方面的思路,前面大概写几篇:<音视频播放疑难杂症分析和解决 :序篇>.<音视频常见问题分析和解决:延时和抖动>.<记一次 ...

  6. 配置snmp_多种设备基于 SNMP 协议的敏感信息泄露漏洞数据分析报告

    作者:知道创宇404实验室 1. 更新情况 2. 事件概述 SNMP协议[1],即简单网络管理协议(SNMP,Simple Network Management Protocol),默认端口为 161 ...

  7. ffmpeg 丢帧 灰屏_音视频常见问题分析和解决:HLS切片丢帧引起的视频卡顿问题排查...

    问题背景: 前两天看读者留言让再写写音视频问题排查方面的思路,前面大概写几篇:<音视频播放疑难杂症分析和解决 :序篇>.<音视频常见问题分析和解决:延时和抖动>.<记一次 ...

  8. 【Android】【TP】TP开发常见问题分析

    TP开发常见问题&分析 1.TP重点关注范围以及checklist 先附录上TP的内部checklist,所有在列内容都为常见问题切比较严重问题,如下: 上下电时序 Operating Vol ...

  9. 用SNMP协议实现系统监控

    系统监测的基本概念及分类: a.系统监测的概述: 如何对现有IT架构的整体以及细节运行情况进行科学.系统和高效地监测是目前各企业运维和管理部门一项非常重要的工作内容.随着当前企业IT环境中服务器.应用 ...

最新文章

  1. Unicode,UTF-32,UTF-16,UTF-8到底是啥关系?
  2. 基于 SpringBoot 的仿豆瓣平台【源码分享】
  3. 面向Tableau开发人员的Python简要介绍(第4部分)
  4. html 页面重复度高,html – CSS背景渐变重复问题
  5. 【转载】用平常语言介绍神经网络
  6. excel 单元格名称 java_Java 创建、编辑、删除Excel命名区域
  7. Codeforces Round #347 (Div.2)_A. Complicated GCD
  8. 高一计算机基础知识课程ppt课件,高一计算机基础课件.ppt
  9. db4o数据库文件_繁忙的Java开发人员指南db4o,使用db4o进行数据库重构
  10. 智能车制作pdf 王盼宝_智能车制作——从元器件、机电系统、控制算法到完整的智能车设计(Word+PDF+ePub+PPT)...
  11. 程序员那些必须掌握的排序算法(上)
  12. Transphorm推出第四代GaN平台及SuperGaN™功率FET
  13. oracle goldengate 数据库复制配置手册
  14. slg游戏客户端框架简析
  15. sip客户端源码c语言,SIP客户端选型
  16. 达梦数据库(DM8)常用功能总结-图形化界面
  17. 使用Python网络爬虫抓取牛客网题目
  18. Java聊天程序设计
  19. 中国联通集团数据安全治理实践经验总结(脱密版)
  20. 【逗老师带你学IT】AD域控 Dsquery 查询命令实例汇总(转载)

热门文章

  1. java蜂鸣节拍器_电子课程设计-电子节拍器的设计.doc
  2. JDK源码系列:AQS(队列同步器)原理
  3. 名悦集团:买车选色有哪些注意事项
  4. 当谈到携程机票产品经理的数据意识,我们在谈什么?
  5. java.lang.OutOfMemoryError GC overhead limit exceeded原因分析及解决方案
  6. 区块链防伪溯源应用场景分析
  7. 一个有用的视频播放器VLC
  8. 几款代码比较工具BeyondCompare、TextDiff、WinMerge等下载
  9. centos7升级pip失败怎么办?
  10. Halcon实例转OpenCV之焊点检测