基于UDP的即时通信工具的设计开发.doc

上传人:laozhun 文档编号:2400736 上传时间:2023-02-17 格式:DOC 页数:29 大小:602.50KB
返回 下载 相关 举报
基于UDP的即时通信工具的设计开发.doc_第1页
第1页 / 共29页
基于UDP的即时通信工具的设计开发.doc_第2页
第2页 / 共29页
基于UDP的即时通信工具的设计开发.doc_第3页
第3页 / 共29页
基于UDP的即时通信工具的设计开发.doc_第4页
第4页 / 共29页
基于UDP的即时通信工具的设计开发.doc_第5页
第5页 / 共29页
点击查看更多>>
资源描述

《基于UDP的即时通信工具的设计开发.doc》由会员分享,可在线阅读,更多相关《基于UDP的即时通信工具的设计开发.doc(29页珍藏版)》请在三一办公上搜索。

1、计算机网络课程设计报告基于UDP的即时通信工具的设计开发江苏大学计算机学院2015年 7月2日目录1 设计要求与开发环境41.1目标与内容41.2 要求51.3 实现要求52 UDP协议52.1 UDP协议简介52.2 UDP的使用62.3 UDP的特性73 程序设计83.1 点对点通信83.1.1设计思路83.1.2具体实现83.2群组即时通信93.2.1设计思路93.2.2服务器111用户类和在线用户112流程图123具体实现134界面设计135实现的功能143.2.3客户端141本地用户类142具体实现143界面设计154项目测试155 过程与总结171 设计要求与开发环境1.1目标与内

2、容(1)任务一,设计一个基于UDP的点对点通信工具,实现点对点的通信,如下图所示,用户发送的信息将在对方用户中显示,显示内容包括“源IP+发送时间+发送内容”。(2)任务二,设计实现一个基于UDP的群组即时通信工具,如下图所示,每个用户发送的信息将在其他用户中显示,显示内容包括“用户名+发送时间+发送内容”。其中功能主要包括:用户注册、用户登录、用户删除、信息发送与接收、信息保存、历史信息查询等1.2 要求(1)熟悉C#.NET开发环境(2)熟悉Socket等相关通信组件(3)通信协议的定义、封装与解析(4)也可以采用自己熟悉的开发语言或工具实现1.3 实现要求1基于UDP的点对点通信工具,实

3、现点对点的通信,用户发送的信息将在对方用户中显示,显示内容包括“源IP+发送时间+发送内容”。 2实现一个基于UDP的群组即时通信工具,每个用户发送的信息将在其他用户中显示,显示内容包括“用户名+发送时间+发送内容”。3 对于2中还要实现功能主要包括:用户注册、用户登录、用户删除、信息发送与接收、信息保存、历史信息查询等。1.4开发环境软件环境:Microsoft Visual Studio2008 使用C#编写硬件环境:计算机学院305电脑,个人笔记本电脑2 UDP协议2.1 UDP协议简介 UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(O

4、pen System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都

5、需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。2.2 UDP的使用在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的QQ就是使用的UDP协议。虽然UDP是一个不可靠的协议,但它是分发信息的一个理想协议。2

6、.3 UDP的特性(1) UDP是一个无连接协议,传输数据之前发送端和接收端不建立连接,当UDP它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。(2) 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。(3) UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。(4) 吞吐量不受拥挤控制算法的调节,只受应用软件

7、生成数据的速率、传输带宽、源端和终端主机性能的限制。(5)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。(6)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。(以上内容摘录自百度百科)3 程序设计3.1 点对点通信3.1.1设计思路 程序开始运行时启动一个接收线程,接收线程中将启用一个固定端口号如8000专门用于接收数据并且处于后台运行状态,也就是说程序启动到结束程序的这一过程中程序一直在监听是否有信息发送到该程序,若

8、接收到数据,则将数据处理后显示在消息窗口;当发送用户要发送消息时,发送用户先输入接收用户的用户信息,程序会接受用户输入的用于发送的内容,经处理后通过UDP协议将用户数据发送出去同时将其显示本地的消息窗口。3.1.2具体实现1 接收线程程序开始运行时接收函数启动开始接收线程并一直在后台运行监听消息,调用的listen()函数中有用于接收的无限循环。private void Receive()/接收函数 thread = new Thread(new ThreadStart(listen);/新建进程 thread.IsBackground = true;/设置为后台进程 thread.Start

9、();/线程开始 2 发送函数按下发送按钮后,程序将自动获取用户输入的目的IP、端口号、要发送的内容最后发送。private void btSend_Click(object sender, EventArgs e)/发送string dstIP = this.IpAddress.Text.ToString();/获取目的IPstring dstPort= this.PortNo.Text.ToString();/获取目的端口string temp = this.SendMessage.Text;/获取要发送消息byte sendData =System.Text.Encoding.UTF8.

10、GetBytes(temp);/将发送的字符串转换为byte/将IP地址字符串转化为IP 地址和端口号实例 udpSender.Connect(IPAddress.Parse(dstIP),Int32.Parse(dstPort);/发送用户开始连接接收用户 udpSender.Send(sendData, sendData.Length); /向接收用户发送消息string dataTime = System.DateTime.Now.ToString();/获取系统时间Message.Items.Add(本机:);/将发送的消息在本地输出Message.Items.Add(dataTime

11、);Message.Items.Add(temp);SendMessage.Clear();/清空输入框3 界面设计3.2群组即时通信3.2.1设计思路群组即时通信是要实现当群组内的一个用户发送消息时其他在线的每个用户要能收到这一消息。参考点对点通信,我们可以这样想,在点对点通信中,发送用户只是对要接收的单个用户发送了消息,现在让群组通信中的客户端即发送用户来实现这一功能只是接收的用户不在是一个而是两个或多个。但这样做在实现发送时会变得十分复杂,较难解决该发给谁这个问题。因为这时对在线用户即接收用户的处理是分散在每个客户端独立地进行,客服端重复工作且较易出错,给客户端带来不必要的负担。因此引入

12、了服务器,由服务器进行这个将消息转发给所有在线用户的过程。客户端只需将要发送的数据发送给服务器就可以了,剩下的工作全部交给服务器处理,服务器将会把每个客户端发送过来的有效数据转发给每个在线用户。当然,服务器同样面临着将消息发给谁的问题。解决好这个问题才有可能做到余下要求的功能。在点对点的通信中,通信的原理是发送方依据接收方的IP地址和端口号组成的IPEndPoint的内容类似于收信人地址来把消息正确送达接收方的。所以在服务器端关于发给谁的这个问题就是把每个要接收的客户端的用于接收的IPEndPoint保存起来组成一个在线用户列表,在发送的时候把它调用出来依据这个在线用户列表对要发送的消息给每个

13、要接收的客户端转发一遍。这样就解决了发给谁这个核心问题。这样服务器将负责在线用户列表的更新和维护,提高效率和正确性的同时也节约了资源。此时,客户端对在线用户的获取只需将服务器处理过后的在线用户列表发送给客户端,客户端接收带有用户列表的数据处理后再将其输出到屏幕。余下的功能就可以依靠这个转发的功能来实现。首先,在服务器创建一个空的用户列表和一个空的在线用户列表。以后当有用户注册时就将其用户信息如用户名、用户密码、在线状态等写入一个空的用户并保存起来。有用户上线就将该用户发送过来的用来接收的IPEndPoint写入这个用户的用户信息中代替原有的无效的内容,同时把这个用户加入到在线用户列表。用户下线

14、时只需修改用户的在线状态和在线用户列表即可。总的设计思路大概就是这样,在服务器建一个用于接收的用户列表,以这个列表的用户内容为依据来转发消息。编写过程中要注意的是服务器和客户端之间的沟通交流,数据在服务器和客户端间传送,双方都应能理解。所以先写服务器再根据服务器的设定来编写客户端。3.2.2服务器服务器的功能较多而且需要用到很多的判断语句。1用户类和在线用户用户类要包含用户的基本信息用户名和用户密码、用户用于接收的IPEndPoint,为了便于用户在用户列表和在线用户列表间的处理在用户类中还增添了一个整型数据用于表示用户在在线用户列表中的位置。在线用户列表是一个用于保存在线用户在用户列表中的数

15、组下标的整型数组。用户列表的容量可以适当扩充,在线用户列表的容量则需根据服务器的处理能力来设置。public class user public string userName;/用户名 public string userKey;/用户密码 public IPEndPoint userRecIPEndPoint;/用户接收IPendPoint public bool status;/用户状态,true在线、false下线 public int position;/在用户列表中的位置 user userlist=new user1000;/创建1000个空用户int nowUserPositi

16、on = new int100;/记录在线用户位置在用户列表的位置即在线用户列表2流程图服务器一启动就一直处于接收数据状态,接收到数据后依据数据的不同转入对相应数据的处理。处理完回到接收数据状态。3具体实现listen ()为主要函数,该函数负责数据的接收和接收对数据的处理,对数据的处理通过调用相应的函数来处理。如登录用户发来的数据中含有登录数据其组成为登录指令+接收端口+用户名+用户密码,各数据段用字符#区隔,登录指令为login,服务器一接收到login#开头的数据就调用登录函数。对收到数据的判别和处理在源代码中将有详细说明,这里不再赘述。private int searchclient(

17、string userName)/查询userName用户是否在用户列表private bool clientLogin(string receiveData,IPAddress dstIP)/登录函数处理用户登录和添加private bool clientleave(string userName)/用户下线函数private void show()/显示当前服务器信息和在线用户并更新用户列表private void send(string sendData,int noRec)/对除noRec在线用户进行群发private void listen()/监听函数private void Re

18、ceive()/启动接收线程private void btnSaveMesssage_Click(object sender, EventArgs e)/保存消息日志private void btnDelete_Click(object sender, EventArgs e)/删除指定用户4界面设计5实现的功能用户的登录、注册、验证;在服务端对用户的删除,指定路径保存消息记录;消息的群发,将在线用户列表发送到在线用户。基于核心的转发功能和用户列表服务器经过适当的改进还可以添加更多的功能。3.2.3客户端客户端和点对点的通信对比就是多了对服务器信息的识别和处理还有用户登录、注册,结构上很相近。

19、1本地用户类本地用户的内容只需简单的用户名和密码还有用于接收的端口号。class user/本地用户类 public static string userName;/用户名 public static string userKey;/用户密码 public static int myRecPort;/本地接收端口号 2具体实现开始会进入login()进入登录窗口停留等待并发送用户信息直到收到服务器登录成功的消息,在进入聊天界面。private bool login()/登录函数private void send(string temp)/向服务器发送数据tempprivate void btn

20、Send_Click(object sender, EventArgs e)/点击发送按钮发送输入的内容private void listen()/监听函数private void Receive()/启动接收线程private void btnSave_Click(object sender, EventArgs e)/保存当前消息框的内容3界面设计 4项目测试测试结果实现了客户端间的群聊,服务器对用户的删除以及对聊天信息的保存。下图是使用点对点通信对服务器进行测试接收到的数据符合预期。余下的图为使用服务器和客户端进行测试的截图。客户端用户hhh客户端用户ggg 服务器5 过程与总结这是一次

21、编程的新体验。读大学两年了没有做出过什么东西,之前大一时虽然有专门的编程课但实际上机和做课程设计的时候总是会感到力不能及很容易遇到错误而且感觉自己无论如何做也解决不了,最后不了了之。这次课程设计虽然是使用从未接触过的C#来编写。开始的时候也遇到了很大的困难,比如对窗体的熟悉过程中,由于之前没有这方面的经验导致即使借了几本书来参考,也没有头绪,尤其是要基于UDP更是不知道怎么办。之后从网上看了部分教学视频开始渐渐找到感觉。试做成功了一个简单的窗口程序。发现C#在某种层次上比C+简单得多。当然后面遇到的困难解决起来比这复杂。每当遇到实在解决不了的问题时,就算卡住半天也不能在放弃了,因为放弃就做不到

22、接下来要实现的功能。有些问题在网上不停的查找和参考最终可能还解决不了,要感谢同学的帮助。第一次写服务器的时候我是基于IP地址来标识用户的,不久就实现了群聊,但是要在不同的电脑才能实现,因为每台电脑在同一个网络中只有一个IP而且每个客户端都使用8000端口接收服务器的消息。接着又依着第一次大致结构重新写了服务器,把用户标识更改为字符,同时创建了用户类把接收用户的地址改为可变的,在这一过程中最难的是用户类的使用,在创建了用户数组后每次运行到更改用户信息的时候就出错。最后在网页上的一个小角落发现在使用数组前还要实例化,使用for循环全部实例化后终于没有这个问题。总之遇到的问题有很多,程序上还有需要完

23、善的地方。最后我想说这次课程设计激起了我对编程的兴趣,毕竟实现了在两台电脑间通信还有群聊。学习和使用了一种新的编程语言。还有这次时间比较仓促对运行错误处理得不好。我觉得平时个人时间是比较充裕的,可是在课程设计短短的时间内对于基础一般的人要确实自己去完成程序达到课程设计的要求实在比较困难,希望老师能考虑这些情况把课程设计的部分内容当作平时练习来布置,适当延长课程设计的周期让大家有机会在平时多锻炼锻炼,就是早点课设。感谢老师。附源代码服务器 用户类using System;using System.Collections.Generic;using System.Linq;using System

24、.Text;using System.Net;using System.Net.Sockets;namespace UDPSever public class user public string userName;/用户名 public string userKey;/用户密码 public IPEndPoint userRecIPEndPoint;/用户接收IPendPoint public bool status;/用户状态,true在线、false下线 public int position;/在用户列表中的位置 窗口一using System;using System.Collect

25、ions.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Net;using System.Net.Sockets;using System.Threading;using System.Timers;using System.IO;namespace UDPSever public partial class Form1 : Form pub

26、lic Form1() CheckForIllegalCrossThreadCalls = false; InitializeComponent(); show(); for (int i = 0; i 1000; i+)/将userlist1000实例化 userlisti = new user(); Receive(); user refuseUser = new user();/拒绝登录用户 user userlist=new user1000;/创建1000个空用户 int nowUserPosition = new int100;/记录在线用户位置在用户列表的位置即在线用户列表 IP

27、EndPoint clientesIPEndPoint = new IPEndPoint100;/保存用户IP/IPEndPoint clientsIPEndPoint = new IPEndPoint100;/保存用户接收端口 int userNumber = -1;/+1表示用户数量用作用户数组下标 int nowUserNumber = -1;/+1表示在线用户数 const int recPort = 8888;/监听端口号 UdpClient udpReceiver = new UdpClient(recPort);/接收的UDP对象 UdpClient udpSender=new

28、UdpClient();/发送的UDP对象 Thread receiveThread;/发送线程 private int searchclient(string userName)/查询userName用户是否在用户列表 for(int i=0;i=userNumber;i+) if (userlisti.userName = userName)/存在用户userName返回其位置 return i; return -1;/不存在返回-1 private bool clientLogin(string receiveData,IPAddress dstIP)/登录函数处理用户登录和添加 str

29、ing userInformation = receiveData.Split(#);/登录数据划分,登录字段组成:登录指令+接收端口+用户名+用户密码 int i = searchclient(userInformation2);/检查登录用户是否在用户列表中 Int32 dstPort = Int32.Parse(userInformation1); if (nowUserNumber = 99 | userNumber = 999)/超出服务器处理能力 refuseUser.userRecIPEndPoint = new IPEndPoint(dstIP, dstPort); byte

30、sendRefuseBytes = System.Text.Encoding.UTF8.GetBytes(refuse); udpSender.Send(sendRefuseBytes, sendRefuseBytes.Length);/通知请求登录用户登录失败 MessageBox.Show(服务器处理能力受限,无法加入新用户);/提示服务器处理能力受限 return false; if (i = -1)/不在用户列表中添加新用户 userlist+userNumber.userName=userInformation2;/添加用户名 userlistuserNumber.userKey =

31、 userInformation3.ToString();/添加用户密码 userlistuserNumber.userRecIPEndPoint = new IPEndPoint(dstIP, dstPort);/更改用户接收IPEndPoint userlistuserNumber.status = true;/更改为在线状态 nowUserPosition+nowUserNumber = userNumber;/添加在线用户位置 userlistuserNumber.position = nowUserNumber;/保存用在线用户的位置 udpSender.Connect(userli

32、stnowUserNumber.userRecIPEndPoint);/建立连接发送允许登录 byte sendBytes = System.Text.Encoding.UTF8.GetBytes(allow + userlistnowUserNumber.userName);/string allowData = allow + userlisti.userName; udpSender.Send(sendBytes, sendBytes.Length);/通知请求登录用户登录成功 send(userlistuserNumber.userName + 登录成功, -1); return tr

33、ue;/返回成功 else/在用户列表中 if (userlisti.userKey = userInformation3)/用户密码正确允许登录 userlisti.userRecIPEndPoint = new IPEndPoint(dstIP,dstPort);/更改用户接收IPEndPoint if (userlisti.status = true)/重复登录 return false; userlisti.status = true;/更改为在线状态 nowUserPosition+nowUserNumber = i;/添加在线用户位置 userlisti.position = no

34、wUserNumber;/保存用在线用户的位置 udpSender.Connect(userlisti.userRecIPEndPoint);/建立连接发送允许登录 byte sendBytes = System.Text.Encoding.UTF8.GetBytes(allow + userlisti.userName);/string allowData = allow + userlisti.userName; udpSender.Send(sendBytes, sendBytes.Length);/通知请求登录用户登录成功 send(userlistuserNumber.userNam

35、e + 登录成功, -1);/通知在线用户有用户上线 return true; refuseUser.userRecIPEndPoint = new IPEndPoint(dstIP, dstPort);/密码错误 byte sendRefuseBytes = System.Text.Encoding.UTF8.GetBytes(refuse); udpSender.Send(sendRefuseBytes, sendRefuseBytes.Length);/通知请求登录用户登录失败 return false; private bool clientleave(string userName)

36、/用户下线函数 int i = searchclient(userName);/查找用户在用户列表位置 if(i=-1)/用户不存在返回失败 return false; if (userlisti.position = nowUserNumber) nowUserNumber-; userlisti.status = false;/用户存在更改为下线状态 send(userlistuserNumber.userName + 下线成功, -1); return true; userlistnowUserPositionnowUserNumber.position = userlisti.posi

37、tion;/更改最后一个在线用户的position为要下线用户的position nowUserPositionuserlisti.position = nowUserPositionnowUserNumber-;/将最后一个的在线用户的用户列表位置给要替换的位置并把在线用户-1 userlisti.status = false;/用户存在更改为下线状态 send(userlisti.userName + 下线成功, -1); return true;/返回成功 private void show()/显示当前服务器信息和在线用户并更新用户列表 serverInformation.Items.

38、Clear(); string name = Dns.GetHostName();/获取主机名 serverInformation.Items.Add(服务器主机名: + name); IPHostEntry me = Dns.GetHostEntry(name); serverInformation.Items.Add(监听端口: + recPort); serverInformation.Items.Add(服务器所有IP地址:); foreach (IPAddress ip in me.AddressList) serverInformation.Items.Add(ip); clien

39、tsList.Items.Clear(); int now_UserNumber = nowUserNumber +1;/当前用户数 string information = 当前用户数:+now_UserNumber.ToString()+ 用户列表; clientsList.Items.Add(information); string allclient = 用户列表#;/发送到客户端的用户列表数据 for (int i = 0; i =nowUserNumber; i+) string userName=userlistnowUserPositioni.userName;/由用户位置得到用户名 allclient += userName + #; clientsList.Items.Add(userName); send(allclient, -1);/刷新客户端用户列表 private void send(string sendData,int noRec)/对除noRec在线用户进行群发 bytesendBytes=System.Text.Encoding.UTF8.GetBytes(sendData); for (int i = 0; i = nowUserNumber; i+)/发送给在线用户 if(i!=noRec)/不是noRec用户 u

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

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号