• 基于WCF 的远程数据库服务访问技术


    原文出处:http://www.lw80.cn/shuji/jsjlw/13588Htm.Htm
    摘要:本文介绍了使用WCF 建立和运行面向服务(SOA)的数据库服务的系统结构和技术要素,分析了WCF 在远程通信方面的优势以及项目基于数据库服务的多层次开发技术,并通过开发具体应用程序来展示基于WCF 架构的远程数据库服务访问技术的编程步骤和技巧。

      
      0 引言
      
      背景:通常情况下,客户端应用程序可以直接连接、访问数据库,并且可以根据具体的需求实现对数据库不同的操作。但是在实际应用中,以下几种情况不适合将数据库暴露给客户端操作:
      1) 数据库居于数据访问的中心位置,并且数据库的数据出于安全性、完整性等要求需要限定客户端对数据库的各种动作,即客户端只能做数据库指定的那些访问操作。
      2) 出于安全性、保密性以及易控制管理等方面的考虑,不能将数据库暴露于公网中让应用程序直接访问,而是将数据库隔离开来,放在私有网段,只是将访问数据库的操作通过服务的方式发布出来。
      在上述情况下就需要应用远程数据库访问服务。数据库服务,既是将对数据库的增删改查等操作或者更加复杂的多表操作等通过服务的方式发布出来。使用者(即客户端程序)不能直接对数据库进行操作,只能通过访问发布的服务进行数据库的操作。这样作为服务端的数据库服务,能轻松提供并限定各种访问数据库操作,避免客户端对数据库的违法操作。客户端与数据库服务之间的耦合度非常松散,使得系统结构更加灵活。
      
      1 WCF 及相关技术简介
      
      Windows Communication Foundation (WCF)是Microsoft 为构建面向服务的应用提供的分布式通信编程框架。使用该框架,开发人员可以构建跨平台、安全、可靠和支持事务处理的企业级互联应用解决方案。
      WCF 整合了.Net 平台下所有的和分布式系统有关的技术,例如.Net Remoting、ASMX、WSE 和MSMQ。它可以跨进程、跨机器、跨子网、企业网乃至于 Internet;以宿主程序而论,可以以ASP.NET,EXE,WPF,Windows Forms,NT Service,COM+作为宿主(Host)。
      WCF 可以支持的协议包括TCP,HTTP,跨进程以及自定义。在WCF 框架下,开发基于SOA的分布式系统将变得非常容易,微软将所有与此相关的技术要素都包含在内。
      面向服务的体系结构(Service-Oriented Architecture,SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。
      这使得构建在各种这样的系统中的服务可以一种统一和通用的方式进行交互。
      
      1.1 WCF 体系结构
      
      在客户端,应用程序通过一个代理来转发对宿主端所提供服务的调用, 而代理拥有和服务相同的操作接口, 另外还有一些附加的代理管理方法。这也就意味着客户端从来不会直接调用服务。当客户端代理接收到来自客户端的调用请求后, 它将消息通过信道链向下传递。
      每个信道都会执行相应的消息的调用前处理, 例如对消息的编码、提供可靠的会话、对消息进行加密等。客户端的最后一个信道则是传输信道, 根据配置的传输方式发送消息给宿主。
      在宿主端, 消息同样通过信道链进行传输。与客户端信道相对应, 宿主端信道也会对消息执行相应的宿主端的调用前处理, 例如对消息的解码、提供会话管理、对消息进行解密等。
      宿主端的最后一个信道则负责将消息发送给消息分发器(Dispatcher) , 由分发器负责调用服务的实例。
      
      1.2 WCF 技术要素与优势
      
      作为基于 SOA 的一个框架产品,WCF 最重要的就是能够快捷的创建一个服务。
      1)Service Class: 一个标记了[ServiceContract]属性的类, 在其中可能包含多个方法。除了标记了一些WCF 特有的Attribute 外, 这个类与一般的类没有什么区别。
      2)Host( 宿主) : 可以是应用程序, 进程如Windows Service 等, 它是WCF Service 运行的环境。
      3)Endpoints: 可以是一个, 也可以是一组, 它是WCF 实现通信的核心要素。
      一个 Endpoint 由三部分组成: Address, Binding, Contract。称为Endpoint 的ABCs:Address 是Endpoint 的网络地址, 它标记了消息发送的目的地。包括结点的IP 地址、端口号和结点名称。
      Binding 描述的是如何发送消息, 例如消息发送的传输协议( 如TCP, HTTP) , 安全( 如SSL, SOAP 消息安全) 。
      Contract 则描述的是消息所包含的内容, 以及消息的组织和操作方式, 例如是oneway,duplex 和request/reply。
      在 WCF 中, 类ServiceEndpoint 代表了一个Endpoint, 在类中包含的EndpointAddress,Binding, ContractDescription 类型分别对应Endpoint 的Address, Binding, Contract。

     

      WCF 有如下优势:

      1) 统一性:WCF 是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合。
      2) 互操作性:由于WCF 最基本的通信机制是SOAP(Simple Object Access Protocol 简易对象访问协议),这就保证了系统之间的互操作性,即使是运行不同的上下文中。
      3) 安全性:WS-Security,WS-Trust 和WS-SecureConversation 均被添加到SOAP 消息中,以用于用户认证,数据完整性验证,数据隐私等多种安全因素。
      4) 兼容性:WCF 充分的考虑到了与旧有系统的兼容性。
     
      2 设计实例分析
      
      2.1 系统设计方案
      
      基于 WCF 服务的数据库访问应用程序架构,对于 B/S 或C/S 模型没有严格的限制,C/S 可以像B/S 模型那样通过访问WCF 对外提供可调用接口获取数据库服务,这种接口通过服务契约(ServiceContract)生成URI 地址,在WEB SERVER 上或Window Service 上进行调用, 所有方法都通过proxy 的机制被引用进去。
      对于需要提供的数据库服务,可以根据具体的需求暴露数据库的访问层:最细的颗粒可以针对每个单表发布服务,如对一张表中数据的查找、插入或删除记录等。也可以对多表提供服务,这种情况下,相当于将DAL(数据访问层)作为数据库服务发布出来,客户端访问服务获取数据后,需要自行处理以得到符合相关业务的数据,并与UI 层绑定。如果需要限制用户对数据库的操作或者需要提供一定业务,也可以将BLL(业务逻辑层)作为服务发布出来。在这种情况下客户端请求数据库服务,可以得到具有一定业务、已经清洗过滤过的数据,并与UI 层绑定。
      
      2.2 结构图
      
      客户端方面有UI(用户表现层)和(BLL)业务逻辑层组成。表现层用以将BLL 产生的数据展示给用户,并直接与用户交互,将用户的操作及用户产生的数据返回给BLL 层处理。业务逻辑层负责处理用户的请求操作,处理用户产生的数据或者将用户请求的数据返回到表现层展示给用户。服务端是在远程服务器上,该服务器使用双网卡或其他技术实现公私网的跨越。
      
      2.3 服务端实现步骤
      
      1. 定义服务契约.在使用WCF 服务模型时,首先定义服务契约,契约定义了终结点所能提供的操作。本例中服务端主要放在数据访问层实现。在本例中,服务端提供了基本的数据库访问操作,例如可以根据输入表名称和ID 查询某记录的方法。该契约接口如下所示:
      [ServiceContract]
      public interface IServerDAL{[OperationContract]
      ArrayList Find(string type,string id) ;}
      该契约放在IDAL 层,定义与客户端交互的契约。需要引入System.ServiceModel 程序集提供的类,添加System.ServiceModel 命名空间中的ServiceContract 特性。
      使用 OperationContract 特性将IServerDAL 的三个数据库操作方法定义为WCF 的操作契约。
      具体实现了服务契约的类放在DAL 层,称为服务类型,是一个继承了IServiceDAL 接口并实现其方法的具体类。如下所示:
      public sealed class ServerDAL : IServerDAL{public ArrayList FindAll(string type){ //具体实现 }
      }
      访问数据库的操作可以由任何数据库访问技术实现,比如.NET 环境下的ADO.NET 数据访问技术、.Net Framework 3.5 以后的LinQ TO SQL、ODBC 或者使用现有的开源数据访问框架(如NHibrate)等实现对数据库的访问。
      对于返回类型,如果返回的是.Net 中的基本类型,如int、string 等类型,可以直接返回,WCF 负责对这些数据的序列化和反序列化;如果返回的是一个自定义的数据模型时,需要在ServiceContract 的接口( 即本例中的IServiceDAL ) 中加入一个[ServiceKnownType(typeof(MyClass))]属性标签,用以指定序列化或反序列化时服务要使用的已知类型,这些数据实体放在Model 层,客户端和服务端都需要引入该dll。
      
      2. 实现宿主程序承载服务
      
      现在服务契约和具体的服务类型都有了,需要一个应用程序域Host 来承载该服务。WCF中承载服务的宿主选择非常灵活,可以是任何.Net 应用程序,包括控制台程序、Windows窗体程序、Web Service 服务、Windows 服务、IIS 等。可根据具体需求灵活选择,如果需要人为控制该服务启动、停止,则可以选择应用程序作为宿主;若希望该服务开机自启动,则可以选择Windows 服务或IIS 等。应用程序中需要使用System.ServiceModel 中的ServiceHost类,关键代码如下:using{ServiceHost host= new ServiceHost(typeof(ServerDAL )){host.Open();……host.Close();}
      
      3. 制定地址和绑定WCF 
      
      终结点包含了地址、绑定和契约。可以通过程序硬编码制定地址和绑定,也可以将宿主程序中的配置文件app.config 添加配置信息。由于配置文件的形式比较灵活,便于修改,一般企业级的应用都采用配置文件的形式配置WCF 服务的地址和绑定。
      在<system.serviceModel>结点下,设置WCF 服务结点的详细信息:
      <service name="ServerDAL" behaviorConfiguration="DefaultBehavior">
      <host>
      <baseAddresses>
      <add baseAddress="http://127.0.0.1:8080/ServerDAL"/>
      </baseAddresses>
      </host>
      <endpoint address="" binding="basicHttpBinding" contract="IDAL.IServerDAL" />
      </service>
      <host>结点制定了服务宿主的基地址http://127.0.0.1:8080/ServerDAL,其地址为ip 地址、端口号加服务名。<endpoint>设置终结点地址,是基地址的相对地址,若为空则表示该终结点跟基地址一样。
      <endpoint>结点还指定了终结点的绑定,该例为binding="basicHttpBinding",表明使用的是basicHttpBinding,该协议代表了HTTP 传输绑定元素与将SOAP 消息编码成文本的绑定元素的组合。WCF 还有很多预定义绑定,例如WSHttpBinding、NetTcpBinding、NetMsmqBinding、WebHttpBinding 等等,可满足绝大部分需求。<endpoint>中的contract 属性设置服务契约,对应本例中的IService。
      至此,运行宿主程序或启动承载服务的系统服务(Windows 服务或IIS 等),数据库服务就可以使用了。在浏览器中输入服务的地址URL,就可以查看服务的WSDL 了。
      
      2.4 客户端实现
      
      客户端方面,需要引入服务端的IDAL 层的dll 和Model 层的dll。客户端需要在通过硬编码或者通过在配置文件的<Client>结点中配置服务端发布服务的地址(Address)、绑定(Banding)和协议(Contract)和结点名称(name)等,并生成一个代理变量访问服务。关键代码如下:
      IServerDAL proxy =new ChannelFactory<IServerDAL>("basicHttpBinding_IServerDAL").CreateChannel();proxy.Find("tableName","elementID");((IChannel)proxy).Close();这样就生成了一个代理变量可以与服务器通信了。这只是使用服务的一种方式,还有至少三种方式生成WCF 客户端访问服务,在此不再过多介绍。
      
      3 结论
      
      使用 WCF 作为数据库访问服务在安全性、数据完整性和对数据服务的使用者的管理上都有明显的优势,而WCF 在数据传输和通信上提供了一个安全、全面的解决方案,使得服务提供者和使用者能灵活的访问、绑定以及操作数据库服务。

    原文出处:http://www.lw80.cn/shuji/jsjlw/13588Htm.Htm
    摘要:本文介绍了使用WCF 建立和运行面向服务(SOA)的数据库服务的系统结构和技术要素,分析了WCF 在远程通信方面的优势以及项目基于数据库服务的多层次开发技术,并通过开发具体应用程序来展示基于WCF 架构的远程数据库服务访问技术的编程步骤和技巧。

      
      关键词:WCF;SOA;数据库服务;远程访问
      
      0 引言
      
      背景:通常情况下,客户端应用程序可以直接连接、访问数据库,并且可以根据具体的需求实现对数据库不同的操作。但是在实际应用中,以下几种情况不适合将数据库暴露给客户端操作:
      1) 数据库居于数据访问的中心位置,并且数据库的数据出于安全性、完整性等要求需要限定客户端对数据库的各种动作,即客户端只能做数据库指定的那些访问操作。
      2) 出于安全性、保密性以及易控制管理等方面的考虑,不能将数据库暴露于公网中让应用程序直接访问,而是将数据库隔离开来,放在私有网段,只是将访问数据库的操作通过服务的方式发布出来。
      在上述情况下就需要应用远程数据库访问服务。数据库服务,既是将对数据库的增删改查等操作或者更加复杂的多表操作等通过服务的方式发布出来。使用者(即客户端程序)不能直接对数据库进行操作,只能通过访问发布的服务进行数据库的操作。这样作为服务端的数据库服务,能轻松提供并限定各种访问数据库操作,避免客户端对数据库的违法操作。客户端与数据库服务之间的耦合度非常松散,使得系统结构更加灵活。
      
      1 WCF 及相关技术简介
      
      Windows Communication Foundation (WCF)是Microsoft 为构建面向服务的应用提供的分布式通信编程框架。使用该框架,开发人员可以构建跨平台、安全、可靠和支持事务处理的企业级互联应用解决方案。
      WCF 整合了.Net 平台下所有的和分布式系统有关的技术,例如.Net Remoting、ASMX、WSE 和MSMQ。它可以跨进程、跨机器、跨子网、企业网乃至于 Internet;以宿主程序而论,可以以ASP.NET,EXE,WPF,Windows Forms,NT Service,COM+作为宿主(Host)。
      WCF 可以支持的协议包括TCP,HTTP,跨进程以及自定义。在WCF 框架下,开发基于SOA的分布式系统将变得非常容易,微软将所有与此相关的技术要素都包含在内。
      面向服务的体系结构(Service-Oriented Architecture,SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。
      这使得构建在各种这样的系统中的服务可以一种统一和通用的方式进行交互。
      
      1.1 WCF 体系结构
      
      在客户端,应用程序通过一个代理来转发对宿主端所提供服务的调用, 而代理拥有和服务相同的操作接口, 另外还有一些附加的代理管理方法。这也就意味着客户端从来不会直接调用服务。当客户端代理接收到来自客户端的调用请求后, 它将消息通过信道链向下传递。
      每个信道都会执行相应的消息的调用前处理, 例如对消息的编码、提供可靠的会话、对消息进行加密等。客户端的最后一个信道则是传输信道, 根据配置的传输方式发送消息给宿主。
      在宿主端, 消息同样通过信道链进行传输。与客户端信道相对应, 宿主端信道也会对消息执行相应的宿主端的调用前处理, 例如对消息的解码、提供会话管理、对消息进行解密等。
      宿主端的最后一个信道则负责将消息发送给消息分发器(Dispatcher) , 由分发器负责调用服务的实例。
      
      1.2 WCF 技术要素与优势
      
      作为基于 SOA 的一个框架产品,WCF 最重要的就是能够快捷的创建一个服务。
      1)Service Class: 一个标记了[ServiceContract]属性的类, 在其中可能包含多个方法。除了标记了一些WCF 特有的Attribute 外, 这个类与一般的类没有什么区别。
      2)Host( 宿主) : 可以是应用程序, 进程如Windows Service 等, 它是WCF Service 运行的环境。
      3)Endpoints: 可以是一个, 也可以是一组, 它是WCF 实现通信的核心要素。
      一个 Endpoint 由三部分组成: Address, Binding, Contract。称为Endpoint 的ABCs:Address 是Endpoint 的网络地址, 它标记了消息发送的目的地。包括结点的IP 地址、端口号和结点名称。
      Binding 描述的是如何发送消息, 例如消息发送的传输协议( 如TCP, HTTP) , 安全( 如SSL, SOAP 消息安全) 。
      Contract 则描述的是消息所包含的内容, 以及消息的组织和操作方式, 例如是oneway,duplex 和request/reply。
      在 WCF 中, 类ServiceEndpoint 代表了一个Endpoint, 在类中包含的EndpointAddress,Binding, ContractDescription 类型分别对应Endpoint 的Address, Binding, Contract。

     

      WCF 有如下优势:

      1) 统一性:WCF 是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合。
      2) 互操作性:由于WCF 最基本的通信机制是SOAP(Simple Object Access Protocol 简易对象访问协议),这就保证了系统之间的互操作性,即使是运行不同的上下文中。
      3) 安全性:WS-Security,WS-Trust 和WS-SecureConversation 均被添加到SOAP 消息中,以用于用户认证,数据完整性验证,数据隐私等多种安全因素。
      4) 兼容性:WCF 充分的考虑到了与旧有系统的兼容性。
     
      2 设计实例分析
      
      2.1 系统设计方案
      
      基于 WCF 服务的数据库访问应用程序架构,对于 B/S 或C/S 模型没有严格的限制,C/S 可以像B/S 模型那样通过访问WCF 对外提供可调用接口获取数据库服务,这种接口通过服务契约(ServiceContract)生成URI 地址,在WEB SERVER 上或Window Service 上进行调用, 所有方法都通过proxy 的机制被引用进去。
      对于需要提供的数据库服务,可以根据具体的需求暴露数据库的访问层:最细的颗粒可以针对每个单表发布服务,如对一张表中数据的查找、插入或删除记录等。也可以对多表提供服务,这种情况下,相当于将DAL(数据访问层)作为数据库服务发布出来,客户端访问服务获取数据后,需要自行处理以得到符合相关业务的数据,并与UI 层绑定。如果需要限制用户对数据库的操作或者需要提供一定业务,也可以将BLL(业务逻辑层)作为服务发布出来。在这种情况下客户端请求数据库服务,可以得到具有一定业务、已经清洗过滤过的数据,并与UI 层绑定。
      
      2.2 结构图
      
      客户端方面有UI(用户表现层)和(BLL)业务逻辑层组成。表现层用以将BLL 产生的数据展示给用户,并直接与用户交互,将用户的操作及用户产生的数据返回给BLL 层处理。业务逻辑层负责处理用户的请求操作,处理用户产生的数据或者将用户请求的数据返回到表现层展示给用户。服务端是在远程服务器上,该服务器使用双网卡或其他技术实现公私网的跨越。
      
      2.3 服务端实现步骤
      
      1. 定义服务契约.在使用WCF 服务模型时,首先定义服务契约,契约定义了终结点所能提供的操作。本例中服务端主要放在数据访问层实现。在本例中,服务端提供了基本的数据库访问操作,例如可以根据输入表名称和ID 查询某记录的方法。该契约接口如下所示:
      [ServiceContract]
      public interface IServerDAL{[OperationContract]
      ArrayList Find(string type,string id) ;}
      该契约放在IDAL 层,定义与客户端交互的契约。需要引入System.ServiceModel 程序集提供的类,添加System.ServiceModel 命名空间中的ServiceContract 特性。
      使用 OperationContract 特性将IServerDAL 的三个数据库操作方法定义为WCF 的操作契约。
      具体实现了服务契约的类放在DAL 层,称为服务类型,是一个继承了IServiceDAL 接口并实现其方法的具体类。如下所示:
      public sealed class ServerDAL : IServerDAL{public ArrayList FindAll(string type){ //具体实现 }
      }
      访问数据库的操作可以由任何数据库访问技术实现,比如.NET 环境下的ADO.NET 数据访问技术、.Net Framework 3.5 以后的LinQ TO SQL、ODBC 或者使用现有的开源数据访问框架(如NHibrate)等实现对数据库的访问。
      对于返回类型,如果返回的是.Net 中的基本类型,如int、string 等类型,可以直接返回,WCF 负责对这些数据的序列化和反序列化;如果返回的是一个自定义的数据模型时,需要在ServiceContract 的接口( 即本例中的IServiceDAL ) 中加入一个[ServiceKnownType(typeof(MyClass))]属性标签,用以指定序列化或反序列化时服务要使用的已知类型,这些数据实体放在Model 层,客户端和服务端都需要引入该dll。
      
      2. 实现宿主程序承载服务
      
      现在服务契约和具体的服务类型都有了,需要一个应用程序域Host 来承载该服务。WCF中承载服务的宿主选择非常灵活,可以是任何.Net 应用程序,包括控制台程序、Windows窗体程序、Web Service 服务、Windows 服务、IIS 等。可根据具体需求灵活选择,如果需要人为控制该服务启动、停止,则可以选择应用程序作为宿主;若希望该服务开机自启动,则可以选择Windows 服务或IIS 等。应用程序中需要使用System.ServiceModel 中的ServiceHost类,关键代码如下:using{ServiceHost host= new ServiceHost(typeof(ServerDAL )){host.Open();……host.Close();}
      
      3. 制定地址和绑定WCF 
      
      终结点包含了地址、绑定和契约。可以通过程序硬编码制定地址和绑定,也可以将宿主程序中的配置文件app.config 添加配置信息。由于配置文件的形式比较灵活,便于修改,一般企业级的应用都采用配置文件的形式配置WCF 服务的地址和绑定。
      在<system.serviceModel>结点下,设置WCF 服务结点的详细信息:
      <service name="ServerDAL" behaviorConfiguration="DefaultBehavior">
      <host>
      <baseAddresses>
      <add baseAddress="http://127.0.0.1:8080/ServerDAL"/>
      </baseAddresses>
      </host>
      <endpoint address="" binding="basicHttpBinding" contract="IDAL.IServerDAL" />
      </service>
      <host>结点制定了服务宿主的基地址http://127.0.0.1:8080/ServerDAL,其地址为ip 地址、端口号加服务名。<endpoint>设置终结点地址,是基地址的相对地址,若为空则表示该终结点跟基地址一样。
      <endpoint>结点还指定了终结点的绑定,该例为binding="basicHttpBinding",表明使用的是basicHttpBinding,该协议代表了HTTP 传输绑定元素与将SOAP 消息编码成文本的绑定元素的组合。WCF 还有很多预定义绑定,例如WSHttpBinding、NetTcpBinding、NetMsmqBinding、WebHttpBinding 等等,可满足绝大部分需求。<endpoint>中的contract 属性设置服务契约,对应本例中的IService。
      至此,运行宿主程序或启动承载服务的系统服务(Windows 服务或IIS 等),数据库服务就可以使用了。在浏览器中输入服务的地址URL,就可以查看服务的WSDL 了。
      
      2.4 客户端实现
      
      客户端方面,需要引入服务端的IDAL 层的dll 和Model 层的dll。客户端需要在通过硬编码或者通过在配置文件的<Client>结点中配置服务端发布服务的地址(Address)、绑定(Banding)和协议(Contract)和结点名称(name)等,并生成一个代理变量访问服务。关键代码如下:
      IServerDAL proxy =new ChannelFactory<IServerDAL>("basicHttpBinding_IServerDAL").CreateChannel();proxy.Find("tableName","elementID");((IChannel)proxy).Close();这样就生成了一个代理变量可以与服务器通信了。这只是使用服务的一种方式,还有至少三种方式生成WCF 客户端访问服务,在此不再过多介绍。
      
      3 结论
      
      使用 WCF 作为数据库访问服务在安全性、数据完整性和对数据服务的使用者的管理上都有明显的优势,而WCF 在数据传输和通信上提供了一个安全、全面的解决方案,使得服务提供者和使用者能灵活的访问、绑定以及操作数据库服务。

    参考:http://blog.csdn.net/chelen_jak/article/details/8521701

  • 相关阅读:
    HTML-DOM实例——实现带样式的表单验证
    HTML-DOM常用对象的用法(select/option/form/table)
    class介绍
    let 和const命令
    页面滚动事件和利用JS实现回到顶部效果
    DOM的利用冒泡做的一个小程序
    BOM的对象总结(location,screen,navigator,history)
    IE下的双外边距浮动bug
    全国计算机三级网络工程技术复习笔记2
    全国计算机三级网络工程技术复习笔记1
  • 原文地址:https://www.cnblogs.com/xifengyeluo/p/8311529.html
Copyright © 2020-2023  润新知