概念

1 OPC是什么

OLE (object linking and embedding) for Process Control

Open Platform Communications

OPC可以被看作是工业设备之间数据交换的一种协议。最新版本的OPC使用的是UA架构(Unified Architecture),是一种跨平台的通用协议,就像英语是通用语言一样。旧版本的OPC使用了DA架构(Data Access)是不支持跨平台的。

2 OPC的特性和好处

OPC UA 对比 OPC DA

最基本的区别就是版本,旧版本的是DA,新版本试UA。

DA基于OPC经典模型,它在应用层之上(DCOM),依赖且只支持WIndows操作系统,而且需要关闭防火墙。然而,UA不依赖于DCOM,因此它是支持跨平台的,例如Linux、MacOS、Windows,OPC DA只允许访问当前数据,不能生成告警和历史事件,而OPC UA在传输层之上,支持历史事件、多层次结构并且提供方法和程序(命令)等特性。

OPC DA:

OPC UA:

OPC DA的局限性之一是安全性不足,因为在当今世界,安全是主要问题,因为系统更频繁地受到一些复杂的病毒和恶意软件的攻击,而这个安全问题在更高版本的OPC UA中得到了解决。

如果硬件支持,优先选择UA架构。DA尽量不要用在公网里。

服务端

1 准备

1.1 VMwareWorkstation

用来安装虚拟机,官方下载即可,测试环境使用的16.x版本。

1.2 Windows 7 64位(虚拟机)

服务端,用来部署opc服务。 选择win7是因为它够老且不会再自动更新,由于选择使用utgard,它对操作系统版本要求比较多,操作系统太新了会报错,随操作系统自动更新也会报错,例如win10的1909版本更新到21xx版本,就不能运行了。

win7 64位专业版镜像
                链接:https://pan.baidu.com/s/1QVYiX_fcPPwOwexIINyjHw 
                提取码:j31x

1.3 opc模拟器

虚拟机上的opc服务,opc服务端。

MatrikonOPCSimulation
                链接:https://pan.baidu.com/s/13PtADnoellrd2cAJsEz2Tw 
                提取码:c06r

1.4 win10(如果需要)

如果一定要使用win10,推荐1806或者1909版本,再新的就不用试了,肯定用不了。

选择好系统之后需要关闭自动更新,关闭防火墙,特此整理了手顺:

系统基础设置:
                        虚拟机装机时需指定一个用户,默认admin,改成Administrator
                        新系统,ping宿主机能通,宿主机ping虚拟机不通,虚拟机关掉防火墙,能ping通
                        关掉系统自动更新:services.msc -> Windows Update 禁用,恢复都改成无操作;        gpedit.msc 计算机配置 --> 管理模板 --> Windows组件--> Windows更新 --> 配置自动更新 --> 禁用
                        新增一个硬盘,系统自动重启,硬盘新建卷(用于安装应用,不安装在C盘)
                        创建FTP目录(用于和宿主机共享文件)
                        切换administrator用户,创建密码,加到DCOM组

安装OPC软件(这里是力控):
                        右键以管理员身份运行安装文件,除了“安装资源程序”其它都正常安装,最后重启一次。
                        右键以管理员身份运行ForceControl,如果不弹出确认弹窗,表示当前用户权限是可以的
                        开发,选择启动程序,除了opcserver其它都可以关掉

运行opc client:
                        matrikon explorer/opc client,连接PCAuto Server,连接正常。至此,opcserver安装成功并且连接正常。

系统权限设置:
                        Administrator创建密码
                        计算机管理,Administrator加到DCOM 用户组里
                        组件管理,计算机修改属性
                        组件管理,OpcEnum修改权限
                        组件管理,opcserver修改权限

注:如果是32位软件运行在64位系统,需要执行 mmc comexp.msc /32 打开组件管理,64位的是dcomcnfg

2 安装VMware

根据官方指导安装即可。

3 安装Windows虚拟机

1core、4G、20G即可。

4 Windows7虚拟机基本设置

4.1 关闭防火墙(DA需要)

4.2 默认用户为Administrator(例子中是admin),修改登录密码(例如:123456)

4.3 计算机 --> 右键属性 --> 远程设置

4.4 使用物理机执行远程连接,用admin/123456登录成功即可

5 Windows7系统备份

为防止系统配置错误,建议对已配置好的虚拟机进行系统备份。本地是把分配的系统文件夹直接压缩了一份,恢复时直接删掉现有的文件夹,再解压出来。(如果有更好的解决方案欢迎交流)。

6 安装MatrikonOPCSimulation

把安装包直接复制到虚拟机,默认安装即可。

7 组件服务相关配置

7.1 配置虚拟机登录权限

打开计算机管理,添加或修改用户到Dcom用户组。

打开组件服务程序

右键我的电脑

点击第一个编辑限制,点击添加,输入admin,确定。         

把admin的远程访问勾上,确定。

重复上述步骤,把几个都点了。

7.4 OPCEnum配置

这个配置权限不对,会报class未注册的异常。

7.3 DCOM服务配置

这里以力控为例,其它同理。如果配置错误,会导致报连接失败的相关错误。

↓ 这是matrikon的服务名称

和上面一个套路,把admin加进去并给上权限。

客户端

1 Windows 10 64 客户端

本地开发环境

2 Java运行环境

jdk8

3 代码及配置项

3.1 maven依赖

<!--utgard --><dependency><groupId>org.openscada.external</groupId><artifactId>org.openscada.external.jcifs</artifactId><version>1.2.25</version></dependency><dependency><groupId>org.openscada.jinterop</groupId><artifactId>org.openscada.jinterop.core</artifactId><version>2.1.8</version></dependency><dependency><groupId>org.openscada.jinterop</groupId><artifactId>org.openscada.jinterop.deps</artifactId><version>1.5.0</version></dependency><dependency><groupId>org.openscada.utgard</groupId><artifactId>org.openscada.opc.dcom</artifactId><version>1.5.0</version></dependency><dependency><groupId>org.openscada.utgard</groupId><artifactId>org.openscada.opc.lib</artifactId><version>1.5.0</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.61</version></dependency>

3.2 同步定时读取

package com.ruoyi.opc.util;
import java.util.concurrent.Executors;import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.core.JIString;
import org.jinterop.dcom.core.JIVariant;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.da.AccessBase;
import org.openscada.opc.lib.da.DataCallback;
import org.openscada.opc.lib.da.Item;
import org.openscada.opc.lib.da.ItemState;
import org.openscada.opc.lib.da.Server;
import org.openscada.opc.lib.da.SyncAccess;public class UtgardAsyncLoop {public static void main(String[] args) throws Exception {// 连接信息final ConnectionInformation ci = new ConnectionInformation();ci.setHost("192.168.222.129");         // 虚拟机ipci.setDomain("");                  // 域,为空就行ci.setUser("admin");             // 虚拟机登录的用户名ci.setPassword("123456");          // 虚拟机登录密码ci.setClsid("F8582CF2-XXXX-11D0-XXXX-00C0F0104305"); //MatrikonOPCSimulation的注册表ID,可以在“组件服务”里看到,如果不对则需要去注册列表里找final String itemId = "g1.test1";    // MatrikonOPCSimulation上配置的项的名字,没有实际PLC,用的模拟器:simulator// 启动服务final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());try {// 连接到服务server.connect();// add sync access, poll every 500 ms,启动一个同步的access用来读取地址上的值,线程池每500ms读值一次// 这个是用来循环读值的,只读一次值不用这样final AccessBase access = new SyncAccess(server, 500);// 这是个回调函数,就是读到值后执行这个打印,是用匿名类写的,当然也可以写到外面去access.addItem(itemId, new DataCallback() {@Overridepublic void changed(Item item, ItemState itemState) {int type = 0;try {type = itemState.getValue().getType(); // 类型实际是数字,用常量定义的} catch (JIException e) {e.printStackTrace();}System.out.println("监控项的数据类型是:-----" + type);System.out.println("监控项的时间戳是:-----" + itemState.getTimestamp().getTime());System.out.println("监控项的详细信息是:-----" + itemState);// 如果读到是short类型的值if (type == JIVariant.VT_I2) {short n = 0;try {n = itemState.getValue().getObjectAsShort();} catch (JIException e) {e.printStackTrace();}System.out.println("-----short类型值: " + n);}// 如果读到是字符串类型的值if(type == JIVariant.VT_BSTR) {  // 字符串的类型是8JIString value = null;try {value = itemState.getValue().getObjectAsString();} catch (JIException e) {e.printStackTrace();} // 按字符串读取String str = value.getString(); // 得到字符串System.out.println("-----String类型值: " + str);}}});// start reading,开始读值access.bind();// wait a little bit,有个10秒延时Thread.sleep(60 * 1000);// stop reading,停止读取
//            access.unbind();} catch (final JIException e) {System.out.println(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));if (null != server) {server.disconnect();}}}
}

3.3 异步定时读取

package com.ruoyi.opc.util;import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.core.JIString;
import org.jinterop.dcom.core.JIVariant;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.da.*;import java.util.*;
import java.util.concurrent.Executors;/*** @author renqing* @date 07/27/2021*/
public class UtgardPsp {private static final int PERIOD = 100;private static final int SLEEP = 1000 * 60 * 10;public static void main(String[] args) throws Exception {// 连接信息final ConnectionInformation ci = new ConnectionInformation();ci.setHost("192.168.222.129");         // 本机IPci.setDomain("");                  // 域,为空就行ci.setUser("admin");             // 本机上自己建好的用户名ci.setPassword("123456");          // 用户名的密码ci.setClsid("F8582CF2-XXXX-11D0-XXXX-00C0F0104305"); //注册表ID,可以在“组件服务”里看到Map<String, String> items = new HashMap<String, String>();items.put("itemId1","g1.test1");items.put("itemId2","g1.test2");items.put("itemId3","g1.test3");items.put("itemId4","g1.test4");// 启动服务final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());// 连接到服务server.connect();AccessBase access = new Async20Access(server, PERIOD, true);// 循环一遍所有的itemidSet<String> keys = items.keySet();for (String key : keys) {String val = items.get(key);access.addItem(val, new DataCallback() {private int count;@Overridepublic void changed(Item item, ItemState itemstate) {System.out.println("[" + (++count) + "],ItemName:["+ item.getId() + "],value:" + itemstate.getValue());}});}access.bind();
//        Thread.sleep(SLEEP);while(true) {}
//        access.unbind();
//        server.dispose();}
}

3.4 同步读取

 public String readSync(String itemIds, Server server) throws JIException, AddFailedException, IllegalArgumentException, UnknownHostException, NotConnectedException, DuplicateGroupException {Group group = server.addGroup();Item item = group.addItem(itemIds);JIVariant value = item.read(false).getValue();return value.getObjectAsString2();}

3.5 根据服务ID连接,规避使用clsid

/*** Create a new instance and a new DCOM session* @param host the host to contact* @param user the user to use for authentication* @param password the password to use for authentication* @param domain The domain to use for authentication* @throws IllegalArgumentException* @throws UnknownHostException* @throws JIException*/public ServerList ( final String host, final String user, final String password, final String domain ) throws IllegalArgumentException, UnknownHostException, JIException{this ( JISession.createSession ( domain, user, password ), host );}/** 使用ip、用户名、密码、域名(可以为空),创建ServerList对象,* 可以推出OPC服务列表,服务名称对应的进程名(ProgressId),使用ProgId可以推出clsid*/
Collection<ClassDetails> detailsList = serverList.listServersWithDetails(new Category[] { Categories.OPCDAServer10, Categories.OPCDAServer20, Categories.OPCDAServer30 }, new Category[] {});for (final ClassDetails details : detailsList) {System.out.println("---------------->ClsId=" + details.getClsId() + " ProgId=" + details.getProgId() + " Description="+ details.getDescription());}serverList.getClsIdFromProgId(progId); // progId是服务名,例如:Kepware.KEPServerEX.V6

3.6 server断线重连

// 使用自动重连控制器包装一次server
AutoReconnectController controller = new AutoReconnectController(serverInstance);controller.connect();

3.7 遍历item

FlatBrowser flatBrowser = server.getFlatBrowser();if (flatBrowser == null) {return false;}try {Collection<String> collection = flatBrowser.browse();return collection.containsAll(list);} catch (Exception e) {e.printStackTrace();}try {TreeBrowser treeBrowser = server.getTreeBrowser();Branch browse = treeBrowser.browse();Collection<Branch> branches = browse.getBranches();for (Branch branch : branches) {Collection<Leaf> leaves = branch.getLeaves();}} catch (IllegalArgumentException e) {e.printStackTrace();} catch (UnknownHostException e) {e.printStackTrace();} catch (JIException e) {e.printStackTrace();}

已测试通过

MatrikonOPC

KEPServer

GRM(广州巨控)

北京力控。读取OPC数据是成功了,但是给操作系统带来的副作用很大。网络设备、磁盘管理器等都变得不可操作,整个操作系统变得很混乱。例如:我的电脑右键属性报错、本地连接右键报错、磁盘管理器报错等,初步怀疑和力控软件有关。

测试未通过

北京亚控(组态王)。理论上是可以的,后面没有精力再试了。

异常处理

异常及错误码

1、未安装
Class not registered. If you are using a DLL/OCX , please make sure it has "DllSurrogate" flag set. Faq A(6) in readme.html. [0x80040154]
org.jinterop.dcom.common.JIException: The system cannot find the file specified. Is the COM Server present ? Please check DCOMCNFG for it's listing. [0x80070002]

2、用户名/密码写错
org.jinterop.dcom.common.JIException: Access is denied, please check whether the [domain-username-password] are correct. Also, if not already done please check the GETTING STARTED and FAQ sections in readme.htm. They provide information on how to correctly configure the Windows machine for DCOM access, so as to avoid such exceptions.  [0x00000005]

3、服务ip写错
org.jinterop.dcom.common.JIException: An internal error occurred. [0x8001FFFF]

4、写错Clsid
org.jinterop.dcom.common.JIException: Class not registered. If you are using a DLL/OCX , please make sure it has "DllSurrogate" flag set. Faq A(6) in readme.html. [0x80040154]

5、属性都写对,服务端配置错误
org.jinterop.dcom.common.JIException: Access is denied.  [0x80070005]

6、opc服务崩了

org.jinterop.dcom.common.JIException: Server execution failed. [0x80080005]

7、服务安装不正确,考虑换个版本试试

org.jinterop.dcom.common.JIException: Interface not registered. [0x80040155]

8、windows版本太高,出现在win10及以上操作系统中,win --> 设置 --> 系统 --> 关于,查看版本,类似2xxx的都不行,最高1909。类似这种都不行,需要回退版本。

org.jinterop.dcom.common.JIException: Message not found for errorCode: 0x80010111

9、------- 汇总

0x8000401A
The server process could not be started because the configured identity is incorrect. Check the username and password.

0x80004005
Unspecified Error

0x800706BA
RPC_S_SERVER_UNAVAILABLE
The RPC server is unavailable

0x800706BF
远程过程调用失败且未执行

0x8007000E
E_OUTOFMEMORY
Not enough memory to complete the requested operation. This can happen any time the server needs to allocate memory to complete the requested operation.

0x80070776
Couldn’t create connection with advise sink,
Reason for error: There is a problem resolving the computer name.
Solution: This problem can be solved by specifying the IP address of the server instead of specifying the computer name

0x80070005
0x80070005 appears in the OPC Client application when it succeeds in launching an OPC Server or OpcEnum, but fails to receive a reply from either of the applications. This error could be caused under several conditions: On the OPC Server PC, the OPC Client User Account does not have the right Access Control List (ACL) permissions in the System-Wide DCOM settings, Access Permissions, Edit Default.
On the OPC Client PC, the OPC Server User Account does not have the right Access Control List (ACL) permissions in the System-Wide DCOM settings, Access Permissions, Edit Limits.

On the OPC Client PC, the DCOM Default Impersonation Level is set to “Anonymous” instead of “Identify”, and the “ANONYMOUS LOGON” Access Control Entry (ACE) does not exist in the OPC Client PC, Access Control List (ACL) permissions in the System-Wide DCOM settings, Access Permissions, Edit Limits.

Failure to obtain a CLSID
OPC Client application failed to find the OPC Server. The two most common causes are:

  1. Failure to find the OPC server in the Windows Registry
  2. Failure to connect to OPCENUM.EXE

Failed to connect to 2.0 data access interface for group … Falling back to 1.0 interface
可能原因:计算机重名或局域网DNS服务故障,或者在不同子网中

0x8001FFFF
设备连接数量超过OPCserver支持的连接量,需要重启电脑即可

0x80010108 The object invoked has
disconnected from its clients.
Re-initialize your OPC Server Connection.
0x80040004 There is no connection for
this connection ID
0x80040005 Need to run the object to
perform this operation
0x80040007 Uninitialized object
0x80040154 Class not registered The OPC Server, or a component needed to
make the OPC connection is not registered
with Windows. This may mean that you simply
need to register a DLL or OCX file.
0x80040155 Interface not registered The OPC Server does not support the
interface that you are trying to connect to.
Examples may include Item Browsing,
Asynchronous I/O or OPC DA v2.x or 3.x
interfaces etc.
0x800401f3 Invalid class string The GUID/CLSID of the specified OPC Server
is not valid.
0x80040200 • Unable to
impersonate DCOM
Client
• Unknown OLE status
code
DCOM security problem, typically on the
Client side. This error typically occurs when
trying to specify a callback address for
Asynchronous I/O.
0x80040202 Cannot Connect Error typically occurs when a call is made to
Advise on the connection point. This often
means that OPCPROXY.DLL is not the same
version on your different computers.
0x80070002 The system cannot find the
file specified.
Re-install your software.
0x80070005 Access is denied. You need to configure your DCOM Security
settings. See our DCOM Tutorial:
http://www.softwaretoolbox.com/dcom Page 6 of 7
Hex Code Description Resolution
0x80070057 The parameter is incorrect. The OPC Server has rejected your request,
indicating that the parameter(s) you specified
are not valid for the type of request being
made. You will need more details on the
actual OPC calls being made between the
Client and Server.
0x8007041d The service did not respond
to the start or control request
in a timely fashion.
Specific to Windows Services. The service did
not start within the allowed time-frame. This
indicates an initialization problem with the
Windows service.
0x800705b4 This operation returned
because the timeout period
expired.
This is a timeout. You may need to increase
your timeout settings.
0x800706ea A floating-point underflow
occurred at the RPC server.
0x80070725 Incompatible version of the
RPC stub.
0x80080005 Server execution failed There is a problem with the OPC Server
preventing it from being started by Windows.
This may be the result of file-permissions,
DCOM Security permissions, or a lack of
resources.
0x80004002 No such interface supported The OPC Server does not support the
interface that you are trying to connect to.
Examples may include Item Browsing,
Asynchronous I/O or OPC DA v2.x or 3.x
interfaces etc.
0x80004005 Unspecified error The most common message seen, that yields
the least information. In these cases you often
need to check the event-logs at your OPC
Server for more information.
0x8000401a The server process could not
be started because the
configured identity is
incorrect. Check the
username and password.
DCOM Configuration permissions. Modify the
identity that the application should run under,
perhaps specify a named account or choose
“Interactive User’.
0x800706ba The RPC server is
unavailable.
The OPC Server could not be contacted. This
is usually the result of a firewall blocking the
application

10、OPCServer:使用Matrikon OPC Server Simulation - ioufev - 博客园使用Matrikon OPC Server Simulationhttps://www.cnblogs.com/ioufev/p/9366426.html查看用法

总结

1、如果不清楚用户组针对哪些服务权限,就不操作用户组。给所需要的服务权限控制上直接加用户就可以了。

2、经测试,客户端的用户名和服务端的一样都是admin,但是密码不同,依然可以调用opc服务端。

3、连接失败的原因,基本都由于服务端的配置(包括授权配置、网络配置),或者程序中参数写错(或找错)导致。

OPC DA 服务端搭建 (附Java 客户端代码)相关推荐

  1. windows 下frp服务启动_内网穿透frp linux服务端搭建和windows客户端使用

    一.Linux 服务端搭建 1.下载安装 wget --no-check-certificate https://raw.githubusercontent.com/clangcn/onekey-in ...

  2. CA双向认证完整实现步骤(附java客户端代码)

    一.基础概念 注:以下概念除专业名词外,均为个人理解,不具备权威性. 1.什么是系统安全管理 置于公网的系统,通常都需要一定的安全管理,据我个人理解,这里的安全管理主要分三个方面: 一是应用内的权限控 ...

  3. ssl证书CA双向认证完整实现步骤(附java客户端代码)(好文章!)

    一.基础概念 注:以下概念除专业名词外,均为个人理解,不具备权威性. 1.什么是系统安全管理 置于公网的系统,通常都需要一定的安全管理,据我个人理解,这里的安全管理主要分三个方面: 一是应用内的权限控 ...

  4. memcached win64位服务端安装和java客户端实例

    项目开发中需要用到memcached缓存记录下来相关操作方便日后复习,如果有错误或遗漏请留言. memcached服务端安装 下载安装包 下载地址 32位系统 1.4.4版本:http://stati ...

  5. 原神服务端搭建架设教程win系统(附客户端+服务端+环境配置)

    原神服务端搭建架设教程win系统(附客户端+服务端+环境配置) 大家好,我是艾西原神一款开放世界冒险3D游戏以七种元素(分别为风.雷.岩.火.水.草.冰)交汇的幻想世界"提瓦特"创 ...

  6. gPRC简介以及Java中使用gPRC实现客户端与服务端通信(附代码下载)

    场景 ProtoBuf的介绍以及在Java中使用protobuf将对象进行序列化与反序列化: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/det ...

  7. 弹弹堂服务器如何修改,弹弹堂端游服务端+手工弹弹堂游戏客户端+GM管理后台+附安裝构建实例教程...

    弹弹堂端游服务端+手工弹弹堂游戏客户端+GM管理后台+附安裝构建实例教程 系统centos 7.2 64位 安装宝塔 yum install -y wget && wget -O in ...

  8. android mqtt服务器搭建,Mqtt从服务端到Android客户端搭建(mqtt服务端搭建)

    一.简介 MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议. 此处不再引入官方文字描述,以个人开发认识浅谈一下 本文分为两部分: 1. M ...

  9. zabbix服务端搭建

    zabbix 是一个基于 WEB 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix 能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定 ...

  10. Spring Cloud Hoxton 版本微服务项目搭建 admin 监控客户端

    Spring Cloud Hoxton 版本微服务项目搭建 admin 监控客户端 前言 在上一篇文章博主已经讲解了admin 管理中心服务项目如何创建,不会的话可以前往学习,传送门:Spring C ...

最新文章

  1. ICCV 2019论文投稿数破纪录,中科院、清华名列前茅,苹果垫底
  2. console线驱动安装_centos7安装docker
  3. 11.6 如何使用内嵌资源类(ResourceRetriever)?
  4. 【HDU4497 GCD and LCM】
  5. Intent传递数据全解
  6. Python练习题:批量删除多个文件夹内的相同文件
  7. 寻仙新马源码一键端_强大,腾讯开源前后端接口开发工具!
  8. POJ - 3080 Blue Jeans(暴力+KMP)
  9. linux单个core的线程,正确使用Core Data多线程的3种方式
  10. 平衡二叉树(AVL树)-详解平衡调整
  11. Git(9)-diff
  12. webkitlineclamp css3,-webkit-line-clamp
  13. Linux里的/dev/null和21和基本符号
  14. test1 exam5定义一个可以精确表示年、月、日、小时、分、秒的结构体
  15. 倒计时 2 天!「2019 嵌入式智能国际大会」全日程大公开!
  16. Javascript之旅——第九站:吐槽function
  17. WiFi语音智能家居控制系统(一)
  18. Excel IRR函数告诉你信用卡分期、贷款的实际利率
  19. react-custom-scrollbars 滚动条组件的简单实现
  20. html中点重置和提交没反应,为什么点击按钮没反应??

热门文章

  1. smartdns使用指南_OpenWrt之SmartDNS 使用教程(PW版)
  2. c++实现串口功能之termios.h头文件研读<二>
  3. ucore lab1 系统软件启动过程 实验报告
  4. JavaWeb——什么是Session及Session的用法
  5. html js设置div可拖动效果
  6. LabVIEW用高速数据流盘
  7. uCore OS Lab 1 系统软件启动过程
  8. Spring事务原理1-动态代理
  9. 梦幻模拟战更新服务器正在维护,“梦幻模拟战2.0”更新维护公告
  10. matlab papr,PAPR问题的MATLAB程序