C_网络编程——2 网络协议基础,进程,同步._第1页
C_网络编程——2 网络协议基础,进程,同步._第2页
C_网络编程——2 网络协议基础,进程,同步._第3页
C_网络编程——2 网络协议基础,进程,同步._第4页
C_网络编程——2 网络协议基础,进程,同步._第5页
已阅读5页,还剩68页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1 C#委托机制委托机制 C#多线程多线程 C#方法方法回调回调 3 C#网络编程网络编程 网网络编程常识络编程常识 C#线程同步线程同步 2 1. 什么是网络编程什么是网络编程 只有主要实现进程(线程)相互之间的通只有主要实现进程(线程)相互之间的通 信和基本的网络应用原理性(协议)功能的程信和基本的网络应用原理性(协议)功能的程 序,才能算是真正的网络编程。序,才能算是真正的网络编程。 3.1 网络编程常识网络编程常识 3 2. 网络编程的层次网络编程的层次 在网络四层次体系结构中的三层已经有了成熟可靠的 实现实体,如图所示。 3.1 网络编程常识网络编程常识 为windows API函数

2、 程序库方式函数和类 VC编程 .NET socket 4 1. Windows Sockets简介简介 (1)Windows Sockets的概念 (2)Windows Sockets的来源 (3)Windows Sockets的版本 3.1 网络编程常识网络编程常识 5 2. 网络程序的工作机制网络程序的工作机制网络上的进程网络上的进程 通信通信 网络程序与传统单机程序的本质区别在于它能能 够与网络上其他电脑(主机)中的程序互通信够与网络上其他电脑(主机)中的程序互通信 息息。因此如何实现网络中不同主机上程序之间 的通信也就成了网络程序实现的最最基础的技 术。在同一台电脑的操作系统中,不同

3、的两个 进程间要进行通信时,通过系统分配的进程号 (process ID)就可以唯一标识某个进程,也就 是说两个相互通信的进程,只要知道对方的进两个相互通信的进程,只要知道对方的进 程号就可以进行通信程号就可以进行通信。 6 通信时其中一个程序将要传输的一段 信息写入它所在主机的Socket中,该 Socket SOCK_STREAM、SOCK_DGRAM 和SOCK_RAW通过与网络接口 (Network Interface Cards,NIC)相连 的传输介质将这段信息发往另外一台主 机的Socket中,使这段信息能够被其他 程序使用,如图所示。 3.1 网络编程常识网络编程常识 7 8

4、网络上所有应用程序的通信都是基于这 样的同一套套接字进行的,套接字在编程 时对用户来说是可见的,如图所示是网络 上两个Windows应用程序通过套接字通信 的过程。 可见套接字winsock屏蔽了下面 TCP/IP协议栈的复杂性,使得在网络编程 看来,两个程序之间的通信实质上就是它 们各自所绑定的套接字之间的通信。 3.1 网络编程常识网络编程常识 9 10 11 1. TCP/IP协议栈协议栈 其实TCP/IP并不是一个单独并不是一个单独的协议, 而是由一系列网络协议所组成的协议集合 (协议族)。这个庞大的协议家族按照分 层结构组织起来构成的有机整体称为网络网络 协议栈协议栈。 3.1 网络

5、编程常识网络编程常识 12 13 2. 编程界面编程界面 在C# 编程中,.NET对套接字封装后 的类集合构成了程序员直接可见的网络网络 应用编程界面应用编程界面,而这个界面之下的一切 则隐藏在神秘的OS内核之中,对应用开 发人员是透明的。 3.1 网络编程常识网络编程常识 14 15 3.2 进程、线程与网络协议进程、线程与网络协议 16 3.2.1 进程和线程进程和线程 进程是对一段静态指令序列(程序)的动态 执行过程,是系统进行资源分配和调度的一个基 本单位。 与进程相关的信息包括:进程的用户标志、正 在执行的已经编译好的程序、进程程序和数据在 存储器中的位置等。 同一个进程又可以划分为

6、若干个独立的执行 流,我们称之为线程。线程可以看作是进程的一 个实例,是CPU调度和分配的基本单位。在 Windows环境下,用户可以同时运行多个应用程 序,每个执行的应用程序就是一个进程。 17 必须认识到线程本身可能存在影响系统性能的 不利方面,才能正确使用线程。不利方面主要 有: (1) 线程也是程序,所以线程需要占用内存, 线程越多占用内存也越多。 (2) 多线程需要协调和管理,所以需要占用 CPU时间来跟踪线程。 (3) 线程之间对共享资源的访问会相互影响, 必须解决争用共享资源的问题。 (4) 线程太多会导致控制太复杂,最终可能造 成很多Bug。 18 3.2.1 进程和线程(续)

7、 u 并行性的主要特点:并发处理 在一个单处理器系统中可以通过分时 处理来获得并发,系统为每个线程分配一 个CPU时间片,每个线程只有在分配的时 间片内才拥有对CPU的控制权,其它时间 都在等待。 19 3.2.1 C#中的多进程中的多进程Process类类 u Process类位于System.Diagnostics名称空间 下,它专门用于完成系统进程的管理任务。 u 可以在本地计算机上启动和停止进程,也 可以向进程查询特定类型的信息。在远程计 算机上,无法启动和停止进程,但可以查询 进程的相关信息。在对进程进行操作时,首 先要创建Process类的实例,其次还需要设置 其对象成员的Star

8、tInfo属性,最后调用它的 Start方法。 20 例例.启动、停止和观察进程启动、停止和观察进程 1. 新建一个名为ProcessExample的Windows应用 程序。 2. 从工具箱中将Process组件拖放到设计窗体。 3. 添加名称空间 : using System.Diagnostics; using System.Threading; 4. 添加“启动记事本”、“停止记事本”和 “观察所有进程”三个按钮,并添加Click事 件代码: 21 private void buttonStart_Click(object sender, EventArgs e) process1.S

9、tartInfo.FileName = notepad.exe; /启动Notepad.exe进程 process1.Start(); 22 private void buttonStop_Click(object sender, EventArgs e) Process myprocesses; myprocesses = Process.GetProcessesByName(Notepad); foreach (Process instance in myprocesses) /设置终止当前线程前等待1000毫秒 instance.WaitForExit(1000); instance.C

10、loseMainWindow(); 23 private void buttonView_Click(object sender, EventArgs e) listBox1.Items.Clear(); Process processes; processes = Process.GetProcesses(); foreach (Process p in processes) /由于访问Idle的StartTime会出现异常,所以将其排除 在外 if (p.ProcessName != Idle) /将每个进程名和进程开始时间加入listBox1中 this.listBox1.Items.A

11、dd( string.Format(0,-301:h:m:s, p.ProcessName, p.StartTime); 24 3.2.2 Thread类 在System.Threading名称空间下, Thread类是用 于创建和控制线程的,对线程的常用操作有:启动 线程、终止线程、合并线程和让线程休眠等。 u启动线程启动线程 在使用线程前,首先要创建一个线程。其一般 形式为: Thread t=new Thread(enterPoint); 其中enterPoint为线程的入口,即线程开始执行 的方法。 。 25 在托管代码中,是通过委托处理线程执行 代码的。 例: Thread t=ne

12、w Thread(new ThreadStart(methodName); 创建线程实例后,就可以调用Start方法 启动线程了 26 u终止线程终止线程 线程启动后,当不需要某个线程继续执行的 时候,就需要终止该线程。终止线程调用Thread 类的Abort方法。 例如:t.Abort(); Abort方法没有参数。当调用Abort方法时, CLR可能不会立即终止线程。 主线程调用子线程的Abort方法后,结束子线 程会占用大量CPU的时间,表面上看就像死机。 为解决这个问题,可以在主线程中调用子线程 对象的Join方法,并在Join方法中指定主线程等 待子线程结束的等待时间。 27 3.2

13、.2 Thread类(续) u合并线程合并线程 Join方法用于把两个并行执行的线程合并为一 个单个的线程。如果一个线程t1在执行的过程中 需要等待另一个线程t2结束后才继续执行,可以 在t1中调用t2的join()方法。 如:t2.Join(); 这样t1在执行到t2.join()语句后就会处于组塞状 态,直到t2结束后才会继续执行。为了解决假如 t2一直不结束的问题,可以在调用t2的Join方法的 时候指定一个等待时间。 如: t2.Join(100); Join方法通常和Abort一起使用。 28 3.2.2 Thread类(续) u让线程休眠让线程休眠 在多线程应用程序中,有时候并不希

14、望某一个 线程继续执行,而是希望该线程停止一段时间, 等待其它线程执行之后再接着执行。这时可以调 用Thread类的Sleep方法,即让线程休眠。 例如:Thread.Sleep(1000); 这条语句的功能是让当前线程休眠1000毫秒。 注意,调用Sleep方法的是类本身,而不是类 的实例。休眠的是该语句所在的线程,而不是其 他线程。 29 3.2.2 Thread类(续) u线程优先级 在C#应用程序中,可以对线程设定五个不同的 优先级,由高到低分别是Highest、AboveNormal、 Normal、BelowNormal和Lowest。在创建线程时如果 不指定其优先级,则系统默认为

15、Normal。 若想让一些重要的线程优先执行,可以使用下 面的方法为其赋予较高的优先级: Thread t=new Thread(new ThreadStart(enterpoint); t.priority=ThreadPriority.AboveNormal; 设置线程的优先级可改变线程的执行顺序,所 设置的优先级仅适用于这些线程所属的进程。当 把某线程的优先级设置为Highest时,系统正在运 行的其它线程都会止。 30 3.2.2 Thread类(续) u线程池 线程池是一种多线程处理形式,线程池为线 程生命周期的开销问题和资源不足问题提供了 很好的解决方案。通过对多个任务重用线程,

16、线程创建的开销被分摊到了多个任务上。 线程池适用于需要多个线程而实际执行时间 又不多的场合 。但是如果线程要求运行的时间 比较长的话,那么此时线程的运行时间比线程 的创建时间要长得多,仅靠减少线程的创建时 间对系统效率的提高就不是那么明显了,此 时就不适合使用线程池技术 31 3.2.2 Thread类(续) u同步 同步指在某一时刻只有一个线程可以访问变 量或者对象。 线程t1对variable1操作时,为了避免其他线 程也对其进行操作,可以使用C#提供的lock语 句将variable1锁定。实现代码为: lock (variable1); variable1+=1; 注意:不要将被同步的

17、对象声明为public。 32 例.在程序中使用线程 1. 新建一个名为ThreadExample的Windows应用程 序 。 2.向设计窗体拖放一个Timer组件。 3.名称空间:using System.Threading; 4.字段声明: StringBuilder sb = new StringBuilder(); Thread thread1; Thread thread2; 5. 代码: private void AppendString(string s) lock (sb) 33 str.Append(s); public void Method1() while(true)

18、 Thread.Sleep(100); /线程休眠100毫秒 AppendString(a); public void Method2() while(true) 34 Thread.Sleep(100); /线程休眠100毫秒 AppendString(b); 6. 启动线程和终止线程按钮的Click事件中添加代码: private void buttonStart_Click(object sender, EventArgs e) sb.Remove(0, sb.Length); timer1.Enabled = true; thread1 = new Thread(new ThreadS

19、tart(Method1); thread2 = new Thread(new ThreadStart(Method2); thread1.Start(); 35 thread2.Start(); private void buttonAbort_Click(object sender, EventArgs e) thread1.Abort(); thread1.Join(10); thread2.Abort(); thread2.Join(10); 7. timer1的Tick事件代码: private void timer1_Tick(object sender, EventArgs e)

20、 if (thread1.IsAlive = true | thread2.IsAlive = true) 36 richTextBox1.Text = sb.ToString(); else timer1.Enabled = false; 键编译并执行,单击启动线程后,等一会再 单击终止线程,查看运行结果。 37 例如在VS2005中新建一个Windows窗体应用程 序,打开解决方案资源管理器树形目录下的 “Program.cs”文件,其代码如下。 static class Program /应用程序的主入口点。 static void Main() Application.EnableVi

21、sualStyles(); Application.SetCompatibleTextRenderingDefa ult(false); Application.Run(new Form1(); 3.2.2 C#3.2.2 C#多线程多线程 38 通过实例化一个Thread对象就可以创建一个 线程。创建新的Thread对象时,将创建新的托管 线程。Thread类接收一个ThreadStart委托或 ParameterizedThreadStart委托的构造函数,该 委托包装了调用Start方法时由新线程调用的方法, 示例代码如下。 /创建线程 Thread thread = new Threa

22、d(new ThreadStart(method); thread.Start(); /启动线程 3.2.2 C#3.2.2 C#多线程多线程 39 上述代码实例化了一个Thread对象,并 指明将要调用的方法method( ),然后启 动线程。ThreadStart委托中作为参数的 方法不需要参数,并且没有返回值。 ParameterizedThreadStart委托一个对象为 参数,利用这个参数可以很方便地向线 程传递参数,示例代码如下。 Thread thread = new Thread(new ParameterizedThreadStart(method); thread.Star

23、t(3);/启动线程并传参数3 40 3.2.3 在一个线程中操作另一个线 程的控件 u 默认情况下,为了防止引起死锁等不安 全因素,C#不允许在一个线程中直接操作 另一个线程中的控件。但是在Windows应用 程序中,为了在窗体上显示线程中处理的信 息,我们可能需要经常在一个线程中引用另 一个线程中的窗体控件。比较常用的办法是 使用委托(delegate)来完成这个工作。 u 例.一个线程操作另一个线程的控件的 方法 。 41 初识委托初识委托 定义委托使用关键字delegate: delegate void SomeDelegate(type1 para1,type2 para2,type

24、n paran); 声明委托: SomeDelegate d; 接着实例化: d = new SomeDelegate(obj.InstanceMethod); 3.2.3 C#委托委托机制机制 42 然后用作某方法的参数: someMethod(d); 最后在此方法的实现代码中使用: private void someMethod(SomeDelegate someDelegate) /使用委托 someDelegate(arg1,arg2,argn); 43 委托是一个特殊的类,它定义了方法的类型, 使得可以将方法当作另一个方法的参数来进行 传递,这种将方法动态地赋给参数的做法,可 以避免

25、在程序中大量使用if-else (switch)语句, 同时也使得程序具有更好的扩展性。 3.2.3 C#委托委托机制机制 44 委托机制尤其适合在使用事件处理的编程模式 或者类的静态方法,以及需要封装和灵活地组 织方法的场合。相对Java等传统面向对象语 言的接口而言,委托具有方便组织方法的特点, 更适合处理事件的响应方法。 45 3.2.4 C#3.2.4 C#方法回调方法回调- -windows程序消息机制程序消息机制 Windows GUI程序的消息循程序的消息循环环 GetMessage ()阻塞方法()阻塞方法 PeekMessage()() 46 主线程维护着整个窗体以及上面的子

26、控件。 当它得到一个消息,就会调用 DispatchMessage方法派遣消息,这会引 起对窗体上的窗口过程的调用。窗口过程 里面当然是程序员提供的窗体数据更新代 码和其它代码 47 线程外操作线程外操作GUIGUI控件的问题:控件的问题: 如果从另外一个线程操作windows窗体上的控件, 就会和主线程产生竞争,造成不可预料的结果, 甚至死锁。因此windows GUI编程有一个规则, 就是只能通过创建控件的线程来操作控件的数 据,否则就可能产生不可预料的结果。 因此,dotnet里面,为了方便地解决这些问题, Control类实现了ISynchronizeInvoke接口,提 供了Invo

27、ke和BeginInvoke方法来提供让其它线 程更新GUI界面控件的机制。 3.2.5 C#3.2.5 C#方法回调方法回调 48 3.2.5 C#3.2.5 C#方法回调方法回调- -线程间和进程间通信机制线程间和进程间通信机制 有些api发送消息需要一个窗口句柄,这种函数可以把消息发送到指定窗口的主线程消息 队列;而有些则可以直接通过线程句柄,把消息发送到该线程消息队列中。 SendMessage PostMessage 49 Invoke或者BeginInvoke方法都需要一个委托对象作为参数。委托类似 于回调函数的地址,因此调用者通过这两个方法就可以把需要调用的 函数地址封送给界面线

28、程。这些方法里面如果包含了更改控件状态的 代码,那么由于最终执行这个方法的是界面线程,从而避免了竞争条 件,避免了不可预料的问题。如果其它线程直接操作界面线程所属的 控件,那么将会产生竞争条件,造成不可预料的结果。 3.2.5 C#3.2.5 C#方法回调方法回调- -Invoke and BeginInvoke Invoke or BeginInvoke 50 使用Invoke完成一个委托方法的封送,就类似于 使用SendMessage方法来给界面线程发送消息, 是一个同步方法。也就是说在Invoke封送的方法 被执行完毕前,Invoke方法不会返回,从而调用 者线程将被阻塞。 使用Begi

29、nInvoke方法封送一个委托方法,类似 于使用PostMessage进行通信,这是一个异步方 法。也就是该方法封送完毕后马上返回,不会 等待委托方法的执行结束,调用者线程将不会 被阻塞。但是调用者也可以使用EndInvoke方法 或者其它类似WaitHandle机制等待异步操作的完 成。 3.2.5 C#3.2.5 C#方法回调方法回调- -Invoke and BeginInvoke 51 C# 的方法回调机制,也是建立在委托基础上的,下面给 出它的典型实现过程。 (1)定义、声明回调: delegate void DoSomeCallBack(type para); DoSomeCall

30、Back doSomeCallBack; (2)初始化回调方法: doSomeCallBack = new DoSomeCallBack(DoSomeMethod); (3)触发对象动作: Opt obj.Invoke(doSomeCallBack, arg); 3.2.5 C#3.2.5 C#方法回调方法回调 Opt obj为目标操作对象,在此假设它 是某控件,Invoke签名: Object Control.Invoke(Delegate method, Params object args) 52 最终作用于对象Opt obj的代码是置于回调方法 体DoSomeMethod( )中的:

31、private void DoSomeMethod (type para) /方法体 Opt obj.someMethod(para); 【例】SocketRecall,方法回调、委托与线方法回调、委托与线 程综合程综合 3.2.5 C#3.2.5 C#方法回调方法回调 53 3.2.6 3.2.6 C#C#线程同步线程同步 在C#里面用于实现线程同步的常用类有如下几 类 1、Mutex类(互斥器),Monitor类,lock方法 2、ManualResetEvent类,AutoResetEvent类 (由EventWaitHandle类派生出来的) 3、ReaderWriterLock类 4

32、、轻量级volatile关键字 【例】ThreadSyncTest 54 建造者模式建造者模式 55 这种模式用于快餐店制作儿童餐。典型的 儿童餐包括一个主食,一个辅食,一杯饮 料和一个玩具(例如汉堡、炸鸡、可乐和 玩具车)。这些在不同的儿童餐中可以是 不同的,但是组合成儿童餐的过程是相同 的。无论顾客点的是汉堡,三名治还是鸡 肉,过程都是一样的。柜台的员工直接把 主食,辅食和玩具放在一起。这些是放在 一个袋子中的。饮料被倒入杯中,放在袋 子外边。这些过程在相互竞争的餐馆中是 同样的 56 实验作业实验作业 麦当劳有两个做汉堡的厨师(工号:11,12) 和三个销售人员(工号:21,22,23)

33、。 厨师生产汉堡,并负责将做好的汉堡放入货架, 货架台大小有限,最多放6个汉堡,11和12不能 同时往货架台上放汉堡,11具有优先权。 销售人员负责销售食品,三个销售人员取食品 时,货架不能为空,三人不能同时取,23优先 权最高,21最低。21卖的最快,取得频率最高, 22次之。 一天的工作量是销售70个汉堡。 57 3.3.2 IP地址与端口 u IP(Internet Protocol)是internet网络设 备之间传输数据的一种协议。本节所讲的端 口不是逻辑意义上的端口,是指TCP/IP协议 中的端口。这一节我们将对IPAddress、 IPHostEntry、IPEndPoint等S

34、ystem.Net命名 空间中的几个类进行简单的介绍。 58 3.3.3 TCP/IP网络协议 u 网络协议 u TCP/IP u IP地址 59 3.3.4 IPAddress类与Dns类 IPAddress类提供了对IP地址的转换、处理等功能。其Parse方 法可将IP地址字符串转换为IPAddress实例。如: IPAddress ip = IPAddress.Parse(“”); IPAddress类提供了7个只读字段: uAny 表示本地系统可用的任何IP地址 uBroadcast 表示本地网络的IP广播地址 uIPv6Any Socket.Bind方法用此字段

35、指出本地系统可用的IP 地址 uIPv6Loopback 表示系统的回送地址 uIPv6None 表示系统上没有可用的网络接口 uLoopback 表示系统的回送地址 uNone 表示系统上没有可用的网络接口 60 3.3.5 IPAddress类与Dns类(续) Dns类提供了一系列静态的方法,用于获取提供本地或远程 域名等功能,常用方法有: 1) GetHostAddresses方法 获取指定主机的IP地址,返回一个IPAddress类型的数组。 函数原形为: public static IPAddress GetHostAddresses(string hostNameOrAddress

36、); 例如: IPAddress ip=Dns.GetHostAddresses(); listBox1.Items.AddRange(ip); 2) GetHostName方法 获取本机主机名。例如:string hostname = Dns.GetHostName(); 61 3.3.6 IPHostEntry类 IPHostEntry类的实例对象中包含了Internet主机的 相关信息。 常用属性有:AddressList属性和HostName属性。 AddressList属性作用:获取或设置与主机关联的IP 地址列表,是一个IPAddress类型的数组,包含了指 定主机的所有IP地址;

37、HostName属性则包含了服务 器的主机名。 在Dns类中,有一个专门获取IPHostEntry对象的 方法,通过IPHostEntry对象,可以获取本地或远程 主机的相关IP地址。 例如: 62 3.3.6 IPHostEntry类(续) listBox1.Items.Add(搜狐新闻所用的服务器IP地址 有:); IPAddress ip = Dns.GetHostEntry().AddressList; listBox1.Items.AddRange(ip); listBox1.Items.Add(本机IP地址为:); ip =Dns.GetHostEntry(Dns.GetHostN

38、ame(). AddressList; listBox1.Items.AddRange(ip); 63 3.3.7 IPEndPoint类 在C#中,IPEndPoint类包含了应用程 序连接到主机上的服务所需的IP地址和 端口信息。 IPEndPoint类常用的构造函数为: public IPEndPoint(IPAddress, int); 其中第一个参数指定IP地址,第二个参 数指定端口号。 例 :IPAddress类、Dns类、IPHostEntry类和 IPEndPoint类的使用方法。 64 3.3.8 套接字 套接字是支持TCP/IP协议的网络通信的基本 操作单元。可以将套接字看

39、作不同主机间的进 程进行双向通信的端点,它构成了单个主机内 及整个网络间的编程界面。套接字通常和同一 个域中的套接字交换数据,各种进程使用这个相 同的域互相之间用Internet协议进行通信。 套接字有两种不同的类型:流套接字和数据 报套接字。 要通过互联网进行通信,至少需要一对套接 字,其中一个运行于客户端,称之为 ClientSocket,另一个运行于服务器端,称之为 ServerSocket。 65 3.3.9 套接字(续) 根据连接启动的方式以及本地套接字要连接的目标, 套 接字之间的连接过程可以分为三个步骤:服务器监听, 客 户端请求,连接确认。 u服务器监听:指服务器端套接字并不定

40、位具体的客户 端套接字,而是处于等待连接的状态,实时监控网络 状态。 u客户端请求:指由客户端的套接字提出连接请求,要 连接的目标是服务器端的套接字。 u连接确认:指当服务器端套接字监听到或接收到客户 端套接字的连接请求时,它就响应客户端套接字的请 求,建立一个新的线程,把服务器端套接字的信息发 给客户端,一旦客户端确认了此信息,连接即可建立。 66 67 3.3.9 套接字(续) 套接字处理数据两种基本模式:同步套接字和异步套 接字。 u同步套接字 其特点是在通过Socket进行连接、接收、发送操作时, 客户机或服务器在接收到对方响应前会处于阻塞状态。它 适用于数据处理不太多的场合。 u异步套接字 在通过Socket进行连接、接收、发送操作时,客户机 或服务器不会处于阻塞方式,而是利用callback机制进行 连接、接收和发送处理,这样就可以在调用发送或接收的 方法后直接返回,并继续执行下面的程序。 68 3.4 面向连接的套接字 IP连接领域有两种通信类型:

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论