A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc

上传人:laozhun 文档编号:4140863 上传时间:2023-04-07 格式:DOC 页数:22 大小:434KB
返回 下载 相关 举报
A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc_第1页
第1页 / 共22页
A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc_第2页
第2页 / 共22页
A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc_第3页
第3页 / 共22页
A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc_第4页
第4页 / 共22页
A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc_第5页
第5页 / 共22页
点击查看更多>>
资源描述

《A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc》由会员分享,可在线阅读,更多相关《A基于网络的虚拟实验平台—VLP2P通信库的设计与实现.doc(22页珍藏版)》请在三一办公上搜索。

1、基于网络的虚拟实验平台VLP2P通信库的设计与实现摘 要随着信息技术的发展,网络无疑为我们带了更多的便利,因此一个好的系统要具有网络功能。针对虚拟实验台系统的实际功能,采用P2P技术作为其网络通讯基础具有很大的优势:降低服务器资源占用,提高通讯传输效率。但由于NAT的广泛使用,使得不同的内网间系统通讯比较困难。希望P2P通讯具有实用价值,穿透NAT实现不同内网间的系统通讯是一个需要解决的重要问题。在基于网络的虚拟实验平台中,有很多功能涉及到网络通讯,为了提高系统的模块化程度,减少系统重复开发量,将网络通信部分独立出来,设计实现名为VLP2P的P2P通讯库。设计中,也设计了通讯库的测试程序。经实

2、际测试,基本达到预期设计目标。关键词:虚拟实验平台;P2P技术;UDP;穿透NAT;Scoket编程Network-based Virtual Experimental PlatformDesign and Implementation of VLP2P Communication LibraryAbstractWith the development of information technology, networks will provide us with more convenience undoubtedly. Therefore, a good system must have

3、network functions. According to real functions of the virtual experiment platform, P2P technology has powerful benefits to decrease probability of using server resources and upgrade the transmission efficiency, as a base of networking communication. While, because of the existence of NAT issues, it

4、is difficult to communicate among different local networks. To make P2P communication get values in real application, an important problem required to solve is the system communication among different networks by penetrating NAT.There are many functions related to network communication in the virtua

5、l experiment platform based on network. For improve modularization of the system and decrease repetitive developing work, the network communication is extracted as an independent part to design and implement P2P communication library named VLP2P. In the thesis, the testing program for communication

6、library is also designed. With real testament, it has proven that the communication library has achieved the initial purpose.Key words: Virtual Experiment Platform; P2P Technology; UDP; Penetrating NAT; Socket programming目录论文总页数:20页1引言11.1.项目背景11.2.项目介绍11.2.1虚拟实验平台11.2.2平台网络通信11.3.项目要求11.3.1功能要求11.3

7、.2B/S与 C/S21.3.3通信协议的选择21.4.项目难点及解决方法21.4.1IP处理问题21.4.2Client之间的通信问题22.网络基础知识介绍22.1.SOCKET编程22.2.P2P网络简介(introduction)33.项目网络通信的实现过程43.1.NAT的一些基本概念43.2.通信过程43.3.通信过程总结74.实现代码及其效果简介84.1.程序主要功能介绍84.2.主要代码介绍84.3.1服务器监听过程主要代码84.3.2客户端连接过程主要代码84.3.3下载实验文本(客户端主要代码)94.3.4下载实验文本(服务器端主要代码)94.3.5P2P下载实验文本(客户端

8、主要代码)104.3.6客户端P2P下载实验文本(服务器端主要代码)114.3.效果演示124.3.1开启服务及客户端登陆124.3.2通过服务器下载实验文本134.3.3退出连接14结 论14参考文献14附 录16致 谢19声 明20 1 引言Internet进行访问。NAT技术可以为TCP、UDP以及ICMP的部分信息进行透明中继。NAT技术具体实现方法是通过IP地址映射来实现IP地址的复用。NAT网关充当了路由器的角色,所有外出的网络包都必须路由到NAT网关;同样,所有由外网发往内网的网络包也必须经过NAT网关。NAT网关通过一定的规则,将由内部网向外部网发送的数据包中的源地址映射为一个

9、Internet合法地址,而将由外向内的数据包中的目的地址替换成相应的内网IP地址。NAT网关有内网接口和外网接口,其中外网接口和Internet相连,必须拥有合法IP地址,内网接口则和内网相连,可以分配任意指定的一个内网IP地址,一般情况下,这个IP地址就是内部主机的默认网关。1.1. 项目背景随着信息技术的发展,网络无疑为我们带了更多的便利,因此一个好的系统必须要具有网络功能,这个功能不仅局域网,那就存在一个穿透NAT的问题,伴随着P2P技术的出现,利用UDP实现P2P网络穿越NAT的即时通讯技术,我们不在为此而烦恼。1.2. 项目介绍1.2.1 虚拟实验平台虚拟实验平台是通过软件编程仿真

10、各种电子器件,可以做各种电路实验及设计性实验、 基本电路实验、 直流电路、 交流电路、 动态电路、 这些功能模块成为虚拟平台与实验者之间的桥梁, 共同构成网上虚拟实验室系统,起到帮助学生完成实验任务。1.2.2 平台网络通信实现虚拟实验平台具有网络基本功能,实现虚拟实验平台具有网络基本功能,客户机和主机,客户机和客户机之间的即时通讯、文件的传输。由于采用了最新的P2P穿透NAT的技术,因此可以实现冲破局域网的限制,实现真正的异地连接,同学可以在家里利用一台普通的能够上网的PC,就能把老师布置的实验作业完成,并且,老师可以通过服务器端,了解进度情况,并且可以适时的指导其实验。1.3. 项目要求1

11、.3.1 功能要求实现虚拟实验平台具有网络基本功能,客户机和主机,客户机和客户机之间的即时通讯、文件的传输。1.3.2 B/S与 C/S 目前的软件系统体系结构一般分为两种形式,一种为大家所熟识的C/S 结构,另一种为B/S 结构。C/S 结构,即Client/Server(客户端/服务器)结构,通过将任务合理分配到Client 端和Server 端,降低了系统的通讯开销,可以充分利用两端硬件环境的优势。B/S 结构,即Browse /Server(浏览器/服务器)结构,就是只安装维护一个服务器,而客户端采用浏览器运行软件,进行浏览、访问、操作数据。最初的管理信息系统基本上是采用C/S 模式开

12、发的,但随着WWW 的广泛应用,目前的管理信息系统已经逐渐开始从C/S 模式向浏览器/服务器B/S 模式转变。B/S 结构的软件所有的维护、升级工作都只在服务器上进行,而客户端能立刻获得最新版本的软件。1.3.3 通信协议的选择主机与客户机之间采用TCP协议,保证其可靠性。客户机之间采用UDP非连接,不可靠的通讯协议,相对于tcp来说,虽然可靠性不及,但传输效率较高。对于即时通信的系统,选择UDP,就是要保证较高的传输效率。1.4. 项目难点及解决方法 1.4.1 IP处理问题 由于涉及到各种局域网,因此需要处理各种私有IP的访问问题。解决方法:采用NAT技术实现私有地址转换成公共有效的地址。

13、1.4.2 Client之间的通信问题解决方法:利用服务器的打洞原理(后详)2. 网络基础知识介绍2.1. SOCKET编程什么是 socket?它是使用 标准Unix 文件描述符 (file descriptor) 和其它程序通讯的方式。Unix 程序在执行任何形式的 I/O 的时候,程序是在读或者写一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数。但是(注意后面的话),这个文件可能是一个网络连接,FIFO,管道,终端,磁盘上的文件或者什么其它的东西。Unix 中所有的东西就是文件!所以,你想和Internet上别的程序通讯的时候,你将要使用到文件描述符。你必须理解刚才的话。现

14、在你脑海中或许冒出这样的念头:“那么我从哪里得到网络通讯的文件描述符呢?”,这个问题无论如何我都要回答:你利用系统调用 socket(),它返回套接字描述符 (socket descriptor),然后你再通过它来进行send() 和 recv()调用。“但是.”,你可能有很大的疑惑,“如果它是个文件描述符,那么为什 么不用一般调用read()和write()来进行套接字通讯?”。答案是:“你可以,但是使用send()和recv()让你更好的控制数据传输。”存在这样一个情况:在我们的世界上,有很多种套接字。有DARPA Internet 地址 (Internet 套接字),本地节点的路径名 (

15、Unix套接字),CCITT X.25地址 (你可以将X.25 套接字完全忽略)。也许在你的Unix 机器上还有其它的。2.2. P2P网络简介(introduction) P2P技术源于局域网共享,其目标是改变人们通过服务器中转交换文件的传统方式,达到自由交换资源的目的。IBM为P2P下了如下定义:系统由若干互联协作的计算机构成,且至少具有如下特征之一:系统依存于边缘化(非中央式服务器)设备的主动协作,每个成员直接从其他成员而不是从服务器的参与中受益;系统中成员同时扮演服务器与客户端的角色;系统应用的用户能够意识到彼此的存在,构成一个虚拟或实际的群体。P2P网络是互联网整体架构的基础,互联网

16、最基本的 TCP/IP协议并没有客户端和服务器的概念,在通讯过程中,所有的设备都是平等的一端。P2P 技术改变了“内容”所在的位置,使其正在从“中心”走向“边缘”,也就是说不再如CS模式将内容存于主要的服务器上,而是存在所有用户的 PC 机上。广义的P2P 网络将 P2P网络划分为纯分散式 P2P网络(如gnutella模型)、超级结点式网络和混合式 P2P网络等大类。本文所讨论的通讯技术属于混合式 P2P网络,各节点之间可以直接建立连接,但网络的构建需要服务器,通过集中认证,建立索引机制。但是这里的服务器仅用于辅助对等节点之间建立连接,对等节点之间直接进行通信,这不同于 C/S 模式中的服务

17、器。如图1 p2p网络传输模型所示: 图1 p2p网络传输模型3. 项目网络通信的实现过程3.1. NAT的一些基本概念NAT(Network Address Translators),网络地址转换:网络地址转换是在IP地址日益缺乏的情况下产生的,它的主要目的就是为了能够地址重用。NAT分为两大类,基本的NAT和NAPT(Network Address/Port Translator)。最开始NAT是运行在路由器上的一个功能模块。最先提出的是基本的NAT,它的产生基于如下事实:一个私有网络(域)中的节点中只有很少的节点需要与外网连接。那么这个子网中其实只有少数的节点需要全球唯一的IP地址,其他

18、的节点的IP地址应该是可以重用的。因此,基本的NAT实现的功能很简单,在子网内使用一个保留的IP子网段,这些IP对外是不可见的。子网内只有少数一些IP地址可以对应到真正全球唯一的IP地址。如果这些节点需要访问外部网络,那么基本NAT就负责将这个节点的子网内IP转化为一个全球唯一的IP然后发送出去。(关于基本的NAT可以参看RFC 1631)3.2. 通信过程 另外一种NAT叫做NAPT,从名称上我们也可以看得出,NAPT不但会改变经过这个NAT设备的IP数据报的IP地址,还会改变IP数据报的TCP/UDP端口。基本NAT的设备可能我们见的不多,NAPT才是我们真正讨论的主角。见图2 NAPT端

19、口映射: Server S1 18.181.0.31:1235 | Session 1 (A-S1) | | 18.181.0.31:1235 | | v 155.99.25.11:62000 v | | NAT 155.99.25.11 | Session 1 (A-S1) | | 18.181.0.31:1235 | | v 10.0.0.1:1234 v | | Client A 10.0.0.1:1234 图2 NAPT端口映射 有一个私有网络10.*.*.*,Client A是其中的一台计算机,这个网络的网关(一个NAT设备)的外网IP是155.99.25.11(应该还有一个内网的I

20、P地址,比如10.0.0.10)。如果Client A中的某个进程(这个进程创建了一个UDP Socket,这个Socket绑定1234端口)想访问外网主机18.181.0.31的1235端口,那么当数据包通过NAT时会发生什么事情呢? 首先NAT会改变这个数据包的原IP地址,改为155.99.25.11。接着NAT会为这个传输创建一个Session(Session是一个抽象的概念,如果是TCP,也许Session是由一个SYN包开始,以一个FIN包结束。而UDP呢,以这个IP的这个端口的第一个UDP开始,结束呢,呵呵,也许是几分钟,也许是几小时,这要看具体的实现了)并且给这个Session分

21、配一个端口,比如62000,然后改变这个数据包的源端口为62000。所以本来是(10.0.0.1:1234-18.181.0.31:1235)的数据包到了互联网上变为了(155.99.25.11:62000-18.181.0.31:1235)。 一旦NAT创建了一个Session后,NAT会记住62000端口对应的是10.0.0.1的1234端口,以后从18.181.0.31发送到62000端口的数据会被NAT自动的转发到10.0.0.1上。(注意:这里是说18.181.0.31发送到62000端口的数据会被转发,其他的IP发送到这个端口的数据将被NAT抛弃)这样Client A就与Serve

22、r S1建立以了一个连接。呵呵,上面的基础知识可能很多人都知道了,那么下面是关键的部分了。看看下面的情况,见图3 NAPT转发过程: Server S1 Server S2 18.181.0.31:1235 138.76.29.7:1235 | | | | +-+-+ | Session 1 (A-S1) | Session 2 (A-S2) | 18.181.0.31:1235 | | | 138.76.29.7:1235 | v 155.99.25.11:62000 v | v 155.99.25.11:62000 v | Cone NAT 155.99.25.11 | Session 1

23、 (A-S1) | Session 2 (A-S2) | 18.181.0.31:1235 | | | 138.76.29.7:1235 | v 10.0.0.1:1234 v | v 10.0.0.1:1234 v | Client A 10.0.0.1:1234图3 NAPT转发过程接上面的例子,如果Client A的原来那个Socket(绑定了1234端口的那个UDP Socket)又接着向另外一个Server S2发送了一个UDP包,那么这个UDP包在通过NAT时会怎么样呢?这时可能会有两种情况发生,一种是NAT再次创建一个Session,并且再次为这个Session分配一个端口号(比

24、如:62001)。另外一种是NAT再次创建一个Session,但是不会新分配一个端口号,而是用原来分配的端口号62000。前一种NAT叫做Symmetric NAT,后一种叫做Cone NAT。我们期望我们的NAT是第二种,呵呵,如果你的NAT刚好是第一种,那么很可能会有很多P2P软件失灵。(可以庆幸的是,现在绝大多数的NAT属于后者,即Cone NAT)好了,我们看到,通过NAT,子网内的计算机向外连结是很容易的(NAT相当于透明的,子网内的和外网的计算机不用知道NAT的情况)。但是如果外部的计算机想访问子网内的计算机就比较困难了(而这正是P2P所需要的)。那么我们如果想从外部发送一个数据报

25、给内网的计算机有什么办法呢?首先,我们必须在内网的NAT上打上一个“洞”(也就是前面我们说的在NAT上建立一个Session),这个洞不能由外部来打,只能由内网内的主机来打。而且这个洞是有方向的,比如从内部某台主机(比如:192.168.0.10)向外部的某个IP(比如:219.237.60.1)发送一个UDP包,那么就在这个内网的NAT设备上打了一个方向为219.237.60.1的“洞”,(这就是称为UDP Hole Punching的技术)以后219.237.60.1就可以通过这个洞与内网的192.168.0.10联系了。(但是其他的IP不能利用这个洞)。呵呵,现在该轮到我们的正题P2P了

26、。有了上面的理论,实现两个内网的主机通讯就差最后一步了:那就是鸡生蛋还是蛋生鸡的问题了,两边都无法主动发出连接请求,谁也不知道谁的公网地址,那我们如何来打这个洞呢?我们需要一个中间人来联系这两个内网主机。现在我们来看看一个P2P软件的流程,以下图为例: Server S (219.237.60.1) | | +-+-+ | |NAT A (外网IP:202.187.45.3) NAT B (外网IP:187.34.1.56) | (内网IP:192.168.0.1) | (内网IP:192.168.0.1) | |Client A (192.168.0.20:4000) Client B (1

27、92.168.0.10:40000)图4 p2p打洞过程 首先,Client A登录服务器,NAT A为这次的Session分配了一个端口60000,那么Server S收到的Client A的地址是202.187.45.3:60000,这就是Client A的外网地址了。同样,Client B登录Server S,NAT B给此次Session分配的端口是40000,那么Server S收到的B的地址是187.34.1.56:40000。 此时,Client A与Client B都可以与Server S通信了。如果Client A此时想直接发送信息给Client B,那么他可以从Server

28、 S那儿获得B的公网地址187.34.1.56:40000,是不是Client A向这个地址发送信息Client B就能收到了呢?答案是不行,因为如果这样发送信息,NAT B会将这个信息丢弃(因为这样的信息是不请自来的,为了安全,大多数NAT都会执行丢弃动作)。现在我们需要的是在NAT B上打一个方向为202.187.45.3(即Client A的外网地址)的洞,那么Client A发送到187.34.1.56:40000的信息,Client B就能收到了。这个打洞命令由谁来发呢,呵呵,当然是Server S。3.3. 通信过程总结 总结一下这个过程:如果Client A想向Client B发

29、送信息,那么Client A发送命令给Server S,请求Server S命令Client B向Client A方向打洞。),然后Client A就可以通过Client B的外网地址与Client B通信了。 注意:以上过程只适合于Cone NAT的情况,如果是Symmetric NAT,那么当Client B向Client A打洞的端口已经重新分配了,Client B将无法知道这个端口(如果Symmetric NAT的端口是顺序分配的,那么我们或许可以猜测这个端口号,可是由于可能导致失败的因素太多,我们不推荐这种猜测端口的方法)。4. 实现代码及其效果简介下面是这个通信的过程的源代码,P2

30、PServer运行在一个拥有公网IP的计算机上,P2PClient运行在两个不同的NAT后(注意,如果两个客户端运行在一个NAT后,本程序很可能不能运行正常,这取决于你的,NAT是否支持loopback translation,当然,此问题可以通过双方先尝试连接对方的内网IP来解决,但是这个代码只是为了验证原理,并没有处理这些问题)。4.1. 程序主要功能介绍主机与客户机连接,客户机向主机发送消息或下载实验文本,主机自行决定客户机下载文本的渠道(通过主机下载或从别的客户机下载)。4.2. 主要代码介绍4.3.1 服务器监听过程主要代码 /准许连接,发送欢迎信息 private void Acc

31、ept(IAsyncResult iar) Socket Remote = (Socket)iar.AsyncState; clientSi = (Socket)Remote.EndAccept(iar); /服务器接受由客户端传来的UDP包,用于记录客户端的UDP端口 UDPS.ReceiveFrom(Data, ref RemoteEP); /异步发送欢迎消息 clientSi.BeginSend(Message, 0, Message.Length, SocketFlags.None, new AsyncCallback(Send), clientSi); 4.3.2 客户端连接过程主要

32、代码private void BTNConnect_Click(object sender, EventArgs e) Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /S1为服务器IP,S2为服务器端口 P = new IPEndPoint(IPAddress.Parse(NewF.S1.ToString(), Int32.Parse(NewF.S2.ToString(); /异步连接开始 sock.BeginConnect(P, new AsyncCallb

33、ack(Connected), sock); void Connected(IAsyncResult iar) Client = (Socket)iar.AsyncState; Client.EndConnect(iar); /向服务器发送一个UDP包,服务器可由此包记录客户端的UDP端口,为P2P打洞作准备 UDPClient.SendTo(Data, SUDPIp); /异步接收从服务器传来的欢迎信息,用来检测连接是否成功 Client.BeginReceive(Data, 0, Data.Length, SocketFlags.None, new AsyncCallback(Receiv

34、e), Client); 4.3.3 下载实验文本(客户端主要代码)/下载实验void DownLoad() RCount = Client.Receive(Data, SocketFlags.None); string String = Encoding.Unicode.GetString(Data, 0, RCount); string StringData = String; while (StringDataStringData.Length - 1 != 0) RCount = Client.Receive(Data, SocketFlags.None); String = Enco

35、ding.Unicode.GetString(Data, 0, RCount); StringData += String; 4.3.4 下载实验文本(服务器端主要代码)/异步接收的回调函数 private void Receive(IAsyncResult iar) Socket client = (Socket)iar.AsyncState; string RevData = Encoding.Unicode.GetString(Data, 0, rev); /0为客户端传来的下载实验信号 if (RevData0 = 0) StreamReader Sreamder = new Stre

36、amReader(openFileDialog1.FileName,Encoding.GetEncoding(GB2312); StringData = Sreamder.ReadToEnd(); client.BeginSend(Data, 0, Data.Length, SocketFlags.None, new AsyncCallback(Send), client);4.3.5 P2P下载实验文本(客户端主要代码) /异步接收函数的回调函数(P2P数据发送者)void Receive(IAsyncResult iar) Socket remote = (Socket)iar.Async

37、State; rev = remote.EndReceive(iar); string S = Encoding.Unicode.GetString(Data, 0, rev); /t为服务端传来的p2p发送信号 if (S0 = t) /解析对方客户机的IP和端口号 S = S.Remove(0, 1); StringBuilder SB = new StringBuilder(); while (S0 != :) SB.Append(S0.ToString(); S = S.Remove(0, 1); S = S.Remove(0, 1); IPEndPoint I = new IPEnd

38、Point(IPAddress.Parse(SB.ToString(), Int32.Parse(S); StreamReader SR = new StreamReader(Path, Encoding.GetEncoding(gb2312);UDPClient.SendTo(Data, 0, Data.Length, SocketFlags.None, (EndPoint)I); void DownLoad() /0为下载实验信号 string M = 0; meg = Encoding.Unicode.GetBytes(M); Client.Send(meg, 0, meg.Length

39、, SocketFlags.None); NS = (FileStream)saveFileDialog1.OpenFile(); StreamWriter SW = new StreamWriter(NS); /接收文件,采用同步阻塞方式 RCount = Client.Receive(Data, SocketFlags.None); string String = Encoding.Unicode.GetString(Data, 0, RCount); string StringData = String; while (StringDataStringData.Length - 1 !=

40、 0) RCount = Client.Receive(Data, SocketFlags.None); String = Encoding.Unicode.GetString(Data, 0, RCount); StringData += String; /t为服务端传来的p2p打洞信号, /解析对方客户机的IP和端口号 StringData = StringData.Remove(0, 1); StringBuilder SB = new StringBuilder(); while (StringData0 != :) SB.Append(StringData0.ToString(); StringData = StringData.Remove(0, 1); StringData = St

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公文档 > 其他范文


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号