职场文秘网

首页 > 心得体会 > 工作体会 / 正文

基于TCPIP协议的网络通信小应用程序课程设计

2020-11-10 10:26:31

XX大学理学院 ( 计算机网络 ) 课程设计 实验时间:
2010学年第二学期 专业年级:
2008级应数X班 实验题目:
基于TCP/IP协议的网络通信应用程序 学生姓名:
学号 自评成绩_95教师评成绩___ 学生姓名:
学号 自评成绩_95_教师评成绩___ 学生姓名______学号 ____自评成绩____教师评成绩___ 学生姓名______学号 ____自评成绩____教师评成绩___ 指导老师:
基于TCP/IP协议的网络通信小应用程序 1. 课程设计的题目及要求 1.1 课程设计题目 掌握基于TCP/IP协议实现网络通信,理解TCP与UDP的不同特性以及实现方式。课程设计要求建立一个基于TCP/IP协议的网络通信小应用程序,实验可采用UDP或TCP,建议基于WINDOWS平台。

1.1.1 功能要求 建立一个基于中心服务器方式即时数据通信平台(IM)。要求如下(*为选做内容):
1. 能进行用户管理,所有用户必须登录到服务器,由服务器维护在线信息。

2. IM(Instant Message)功能:用户登录后能进行实时多方点到点短信息通信,如聊天;

3. 能选择要求服务器进行转发服务;

4. 能保存通信记录到数据库(SQL Server或其他桌面型数据库);

5. 能进行双方文件传输,能显示进度;

6. 支持断点重传。(检查时需有功能随时中断传送,并在下次启动能显示重传状态);

*7. 数据包加密;

8.实时语音双向传送功能;

*9.多方通话功能;

10.界面设计要求布局合理,信息清晰。

1.1.2 对于所有功能的要求 1) 要求清晰描述所设计的应答机制,数据包格式,所用数据结构及其相应算法,机密机制等;

2) 对于功能实现要求描绘实现方法,流程。

2. 开发工具、软硬件环境简介 2.1 开发工具 开发工具:Microsoft Visual Studio 2008 2.2 软硬件环境 2.2.1 软件环境 l 操作系统:Windows XP/Windows 7 l 开发软件:Microsoft Visual Studio 2008 l 开发语言:C#语言 l 平台:Microsoft.NET Framework v2.0 2.2.2 硬件环境 l 分辨率:1000×750 l 服务器:
PentiumIII 500以上或更高;

内存:128M以上;

硬盘:至少40G以上;

l 工作站:
PentiumII 266以上微机;

内存:64MB 硬盘:
至少5G以上;

3. 程序实现的基本思想 3.1 程序设计分析 本设计实现的基于TCP/IP协议的网络通信小应用程序,实际上是一个基于Socket的聊天室。聊天室主要由聊天室服务器和聊天室客户端组成。聊天室服务器负责管理和客户端连接并发送消息给客户端;
聊天室客户端负责接收或者发送聊天消息,登录聊天室服务器等。

一个聊天室服务器应该支持多个聊天室客户端进行同时连接。聊天室服务器和聊天室客户端之间根据聊天协议进行通信。

3.2 基本思想 程序的实现主要分为两大部分,即服务器部分和客户端部分。程序首先设计聊天室的服务器,再设计客户端部分,最后生成可执行文件。

1. 服务器 服务器端管理着聊天任务,它维持着一张当前在线用户的列表,转发用户发送来的消息。设计思想如下:
3) 利用控件设计窗体;

4) 功能实现;

Ø 监听本机IP地址中的一个指定的端口;

Ø 当有客户端向该端口发出请求时,服务器程序立刻建立一个与该客户端的连接并启动一个新的线程来处理该客户端;

Ø 根据客户端发送来的各种不同的请求,执行相应的操作,并将结果返回给客户端。

5) 运行调试。

2. 客户端 客户端应用程序包含用户登录窗口和用户聊天的主窗口,它允许用户登录到服务器,可以向服务器发送消息,同时可以接收从服务器返回的信息。

1) 设计登录窗体和聊天窗体;

2) 基于课程设计的要求实现各窗体对应的功能;

Ø 向服务器发送连接请求;

Ø 得到服务器程序的确认后,建立与服务器的连接,并获得与服务器交互的流通道;

Ø 通过网络流通道与服务器端的程序进行数据通信。

3) 运行调试。

4. 系统功能框架图、系统流程图 4.1 功能框架图 图1 功能框架图 4.2 系统流程图 图2系统流程图 5. 具体实现过程 5.1 设计准备 5.1.1 TCP的运用 客户端只能和服务器通信,无法和另外一个客户端直接通信。为了使两个客户端能相互通信,所有的客户一律先把聊天信息发给服务器,并告诉服务器改信息是发送给哪个客户的,服务器收到信息后,再将该信息转发给另外一个客户。本设计的实现主要用了TcpListener类用于用于侦听和接受传入的连接请求。

基本方法:
表1 TCP连接基本方法 TcpListener类基本方法 作用 Start 启动监听 Stop 关闭TcpListener并停止监听请求 AcceptSocket 在同步阻塞方式下获取并返回一个用来接收和发送数据的Socket对象,同时从传入的连接队列中移除该客户端的连接请求 5.1.2 Socket套接字的运用 本设计中自定义了通信程序的可识别命令(见以下第三小点),即自定义的简单协议。故程序中为支持自定义的协议,采用套接字来实现。

根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为服务器监听,客户端请求,连接确认三个步骤。

n 服务器监听:服务器套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

n 客户端请求:由客户端的套接字提出连接请求,要连接的目标是服务器的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器套接字的地址和端口号,然后再向服务器套接字提出连接请求。

n 连接确认:当服务器套接字监听到客户端套接字的连接请求时,它就响应客户端套接字的请求,把服务器套接字的信息发给客户端,一旦客户端确认了此信息,连接即可建立。而服务器套接字继续监听其他客户端套接字的连接请求。

服务器和客户端必须分别进行编程,它们之间的连接如下图所示。

图3 服务器与客户端的连接图 5.1.3 通信程序中可识别命令的定义 程序中定义的可识别命令格式为两个一位整数拼接成的字符串,每位的含义如下:
第一位 第一位为0:客户机向服务器发送的命令 第一位为1:服务器向客户机发送的命令 “01“-离线 “02“-请求在线列表 可以识别的命令格式 “03“-请求对所有人闪屏振动 第二位 服务端 “04“-请求对指定用户闪屏振动 “05“-请求广播消息 “06“-请求对指定用户发送文件 要求转发给指定用户的用户名 :转发给指定用户 “11“-服务器要求客户机更新在线列表 客户端 “12“-服务器要求客户机做闪屏振动 default-接受用户消息或者系统消息的正文 6. 服务器具体设计 6.1.1 窗体设计 新建一个Windows窗体,命名为Form1.cs,主要用于连接服务器。只有建立了聊天室服务器,客户才能连接到上面,从而进行聊天。服务器建立之后,一般处于监听状态,等待客户机的连接申请。

窗体用到的主要控件如下表所示。

表2 主要控件 控件类型 控件名字 用途 按钮 两个按钮,分别用于连接服务器和退出连接 标签 两个标签,一个为“端口号”,另一个为显示“默认端口号” 文本框 两个文本框,一个用于用户输入端口号,另一个用于显示服务器连接等系统消息 图4 窗体设计图 6.1.2 编码 1) 创建服务器 这部分程序的编写主要是实现“获得有效的端口号和IP地址”,设计要点:
l 自动获取IP地址 IPAddress _ip = new System.Net.IPAddress(Dns.GetHostByName(Dns.GetHostName()).AddressList[0].Address); l 可以自主选择是否输入端口号 端口号是进程的标识,端口号范围从0到65535。由于1000以内的端口大多被标准协议占用,所以程序中可以自由使用的端口号一般都用大于1000的值。

若输入端口号,程序设置了有效端口号的范围为1023与65535之间。若端口有效则连接服务器,并提示相应的信息;

默认端口号设置为8888 若没有输入端口号,或者端口号无效,则程序自动使用默认端口号连接服务器。

代码如下:
private void button1_Click(object sender, EventArgs e) { this.button1.Enabled = false; string portParam; portParam = textBox_port.Text; if (portParam != string.Empty) { if (!int.TryParse(portParam, out _port) || _port < 1023 || _port > 65535) { _port = 8888; textBox1 .AppendText (“端口号不合法,默认端口号被接受!“); } } textBox1 .AppendText (“服务器已启动,正在监听...\n“); textBox1 .AppendText (string.Format(“服务器IP:{0}\t端口号:{1}\n“, _ip, _port)); _tcpl =new TcpListener (_ip, _port); _tcpl.Start(); trd = new Thread(new ThreadStart(this.ThreadTask)); trd.Start(); } 2) 线程监听和执行 由服务器和客户端的聊天室模型可以看出,服务器跟客户端的连接以及客户端之间的连接都是通过执行流实现的,即每一个独立的执行流都是一个线程。编写线程监听和线程执行体监听来自多个客户端的请求。

l 线程监听 在创建服务器代码中,可以看到若输入端口号有效,则执行TcpListener类侦听和接受传入的连接请求,并开启线程调用ThreadTask方法。

ThreadTask方法要点:
1) Socket套接字接受连接方法;

2) 验证用户名是否唯一,若当前哈希表没有该用户允许连接,否则连接失败;

3) 调用线程执行体;

4) 向所有用户发送系统消息,AppendText方法在文本框中追加入系统消息,并用foreach循环将系统消息传给各个客户端。

l 线程执行体 线程执行体主要用于客户端和服务器转发消息。线程执行体实际上也是聊天室中服务器端的聊天依据,即我们自定义的协议解析。这部分的程序流程如下图。

图5 客户端程序流程图 5) 退出连接 编程要点:(1)TCP停止监听;

(2)清除在线列表。

代码如下:
private void button2_Click(object sender, EventArgs e) {if (_tcpl != null) { _tcpl.Stop();} //关闭客户端连接并清理资源 if (_transmit_tb.Count != 0) { foreach (Socket session in _transmit_tb.Values) { session.Shutdown(SocketShutdown.Both); } _transmit_tb.Clear(); _transmit_tb = null; } Close();} 6.2 客户端具体设计 6.2.1 登录窗体 1. 窗体设计图 新建一个Windows窗体,命名为login_frm.cs,主要用于验证登录信息,保证登录的用户不重复,端口号和IP地址有效。

主要控件如下表所示:
表3 用户端登录界面的窗体设计 控件类型 控件名字 用途 框架 为一组控件添加一个有标题的框架“请登录” 标签 三个标签,分别为“用户名”、“服务器IP”、“端口号”,提示相应TextBox的信息 文本框 三个文本框,一个用于输入用户名,另外两个用于显示服务器IP和端口号,也可根据实际情况输入合法的服务器IP和端口号 按钮 两个按钮,分别为“登录”和“取消”,前者为登录聊天室,点击后者将会关闭登录界面 图6 用户登陆界面 2. 程序要点 1) TCP连接 新建一个TCP连接类TCPConnection,初始化IP地址、端口号和TcpClient新实例,使用指定的IP地址和端口号连接到TCP主机。

2) 验证登录信息 用户输入用户名、服务器IP地址和端口号,若是输入的IP地址无效,则提示“IP地址不合法”;
如果输入的端口号无法转化为等效的32位有符号整数,或不在1024-65535之间,则提示“端口号不合法”。否则则进行服务器连接。

3) 向服务器发出连接请求并向服务器发送用户名以确认身份 如果客户端连接不到服务器,则提示“无法连接到服务器,请重试”,不然向服务器发送用户名以确认身份,将输入的用户名转化为UTF-16格式的编码,写入NetworkStream,再进行读取,若是已经存在,则提示“您的用户名已经被使用,请尝试其他用户名!“,如果不存在,则获取当前登录窗体的文本,并进入聊天界面。

6.2.2 聊天窗体 l 窗体设计 新建一个Windows窗体,作为一个聊天的界面。

选择聊天室则进行广播,选择悄悄话则进行一对一聊天,点对点地发送文件。还可修改皮肤颜色,对发送数据进行加密、解密。

窗体用到的主要控件如表所示。

表4 客户端主界面的聊天窗口设计 控件类型 控件名字 用途 图片框 两个图片框,用于显示图像 标签 八个标签,其中两个分别提示当前用户和服务器IP、端口号,另外六个提示相应的文本框内容或操作 有格式文本控件 一个有格式文本控件,提供高级文本输入和编辑功能,显示通信内容 文本框 五个文本框,一个用于输入待发送的内容,两个分别显示加密或解密后的内容,其它两个分别显示待发送和已接收的文件所在路径 文本框 一个文本框,下拉式显示当前在线的所有用户名,可用于选择接收方 单选框 两组单选框,一组用于选择皮肤颜色,含三个;
一组用于选择聊天室还是悄悄话 进度条 两个进度条,显示文件传输和保存进度 按钮 十个按钮,分别用于显示皮肤颜色,保存、消除聊天记录,选择、发送、保存文件,加密、解密发送信息,关闭界面 l 线程执行体 这部分是与服务器相对应的。当客户端连接到服务器后,服务器立刻建立一个数据接收的独立线程。在接收线程中,对命令进行解析处理。程序流程如下图。

图 7 客户端程序框图 l 功能模块 1. 聊天功能 1) 一对多聊天 在聊天室模式下进行聊天信息发送,则将相关信息写入网络流,并向服务器发送广播请求。本地信息接收框会显示聊天状态、发送时间和信息内容,其它所有在线用户会显示发送方用户名、发送时间和信息内容。

相关代码:
//如果是聊天室模式则向服务器发送广播请求 if (broadcast_rb.Checked) { localTxt = string.Format(“[广播]您在 {0} 对所有人说:\r\n{1}\r\n\r\n“, DateTime.Now, msg); sendTxt = string.Format(“[广播]{0} 在 {1} 对所有人说:\r\n{2}\r\n\r\n“, _username, DateTime.Now, msg); //发送广播请求 _nws.Write(new byte[] { 0, 5 }, 0, 2); //_nws是用于发送和接收信息的网络流 } 2) 一对一私聊 选择进行“悄悄话”,则需要在当前在线用户在选择一方进行聊天,没有选择用户则无法进行通信,会有提示“请选择一个接收者!\n如果没有接受者可选,表明当前只有您一个人在线”。

发送方会接收到消息,提示发送时间、接收者的用户名和发送的内容,接收方会接收到发送方的用户名、发送时间和发送的内容。

2. 聊天记录 1) 保存聊天记录 点击保存聊天记录,会创建一个SaveFileDialog新实例,另存文件类型设定为*.txt,输入保存的文件名,就会将当前接收信息文本框的所有内容以文本文件保存。

private void save_btn_Click(object sender, EventArgs e) { DialogResult ret; SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = “文本文件(*.txt)|*.txt“; sfd.AddExtension = true; if ((ret = sfd.ShowDialog()) == DialogResult.OK) { chatrcd_rtb.SaveFile(sfd.FileName, RichTextBoxStreamType.PlainText); } } 2) 清除聊天记录 点击清除聊天记录的按钮后,出现提示信息“确实消除吗?消除后不可恢复。”选择确定则调用clear()方法将当前的接收信息框的内容全部清空。

图8 清除聊天记录提示窗口 3. 文件传输 l 选择文件 点击“选择文件”,进入打开文件对话框,根据文件类型筛选文件,找到要发送的文件,点击确定后,读取所选文件所在路径名。

l 发送文件 这一功能只能在“悄悄话”中实现,在“聊天室”模式下会提示“不能在聊天室发送文件”,还需要选择一个接收方,否则会提示“请选择一个接收者!\n如果没有接受者可选,表明当前只有您一个人在线”。如果文件路径名为空,则提示“请选择文件传输路径”,否则,根据路径名为指定的路径名初始化StreamReader的一个新实例sr,读取文件内容,关闭sr,并释放与读取器相关的所有系统资源,并启动控制发送进度条的定时器。

l 保存文件 点击接收文件,弹出保存文件对话框,选择文件保存路径;
为指定路径的指定文件初始化StreamWriter新实例,使用TextWriter.WriteLine(String value)方法将后跟行结束符的字符串写入文本流,同时启动控制进度条的定时器。

4. 数据加密 这部分采用RSA算法来实现。先初始化RSA对象,再使用RSA算法进行解密和加密。下表是RSA算法应用方法的说明。

表5 算法应用方法的说明 名称 说明 Encrypt方法 使用RSA算法对数据进行加密。该方法有两个参数,第一个参数是被加密的字节数组,第二个参数是填充方式(true表示使用OAEP方式填充,false表示使用PKCS#1.5版填充),如果操作系统是Windows XP及其以上版本,可以使用true,如果是Windows 2000及其以上版本,使用false Descrypt方法 使用RSA算法对数据进行加密。其它内容与上相同。

具体代码实现如下:
/// <summary> /// 使用RSA算法进行解密 /// </summary> /// <param name=“text“>要加密的字符串</param> /// <returns></returns> private string RSAEncrypt(string text) { RSACryptoServiceProvider rsa = GetRSAProviderFromContainer(“rsa1“); byte[] bytes = Encoding.Unicode.GetBytes(text); byte[] encryptedData = rsa.Encrypt(bytes, true); return Convert.ToBase64String(encryptedData); } /// <summary> /// 使用RSA算法进行解密 /// </summary> /// <param name=“text“>要解密的字符串</param> /// <returns></returns> private string RSADescrpt(string text) { RSACryptoServiceProvider rsa = GetRSAProviderFromContainer(“rsa1“); byte[] encryptedData = Convert.FromBase64String(text); byte[] decryptedData = rsa.Decrypt(encryptedData, true); return Encoding.Unicode.GetString(decryptedData); } /// <summary> /// 获取初始化RSA对象 /// </summary> /// <param name=“containerName“>密钥容器名</param> /// <returns>RSA对象</returns> private static RSACryptoServiceProvider GetRSAProviderFromContainer(string containerName) { CspParameters cp = new CspParameters(); //将 ProviderType初始化为值24,该值指定PROV_RSA_AES提供程序 cp.ProviderType = 24; //如果不存在名为containerName的密钥容器,则创建之,并初始化cp //如果存在,则直接根据它保存的内容初始化cp cp.KeyContainerName = containerName; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); return rsa; } 7. 运行结果及分析 7.1 服务器 创建连接后,服务器一直处于监听状态,同时用AppendText方法不断追加文本,显示系统消息在文本框中。示意图如下。

图9 服务器界面 7.2 客户端 7.2.1 登录窗体 登录窗体的设计只涉及验证用户名是否唯一、端口号是否有效、服务器IP是否合法。并没有提供新用户的注册,这是本设计的不足之一。如果端口号不正确,用户名不唯一,程序都提供相应的提示。

图10 服务器登陆错误提示 7.2.2 聊天窗体 1. 聊天主窗体 图11 聊天主窗体 2. 保存聊天记录 点击聊天窗体的“保存聊天记录”按钮,弹出对话框如下图,命名文件名字,按“保存”就可得到存储聊天记录的txt文本。

图12 保存聊天记录窗口 txt内容显示图:
图13 消息记录 3. 文件传输 文件传输进度效果图:
图14 文件传输进度效果图 4. 数据加密 图15 数据加密效果图 接收方内容显示图:
图16 接收方内容显示图 8. 总结 8.1 XX总结 这次课程设计虽然总体感觉很难,但在这个过程中学到了很多新的知识。本次课程设计建立一个基于TCP/IP协议的网络通信小应用程序,它的功能类似于我们生活中经常使用的QQ,我想每个做了这个课程设计的同学,至少都学到了一点,那就是知道我们所用的QQ软件是用什么怎么开发出来的。以下是我做课程设计的几点总结。

程序设计知识方面,这次的设计涉及了TCP,Socket套接字,线程,网络流等网络应用编程知识。可以说对于这些知识我都很陌生。开始设计时,通过书籍查阅,并利用视频学习才弄清了整个设计的思路。这才使整个设计找到了起点。通信应用程序两个客户之间的通信必须通过客户端来实现,因此分别设计服务器和客户端是必要的。对于服务端,启动服务器后TcpListener监听端口,当有客户端连接后,通过AcceptSocket返回与客户端连接的Socket对象,然后通过读写Socket对象完成与聊天室客户端的数据传输。而客户端启动后,则创建Socket对象并通过对象连接服务器,成功后通过socket完成数据的接收和发送。此外,服务器和客户端的每个连接都是线程的使用。

程序设计遇到的问题方面,一方面是线程Thread类的使用,经常出现各种错误。比如,运行客户端程序后,用可执行文件打开另外一个窗口进行通信,程序就会出现如下图的错误,并显示“线程间操作无效”,但是如果两个窗口同时是用可执行文件打开,则不会出现这样的错误。另一方面是数据加密与解密的设计,主要使用了RSA算法。所遇到的问题是解密的设计一直没法运行成功。出现错误的现象是运行的两个聊天窗体同时消失。最后我们并没有将解密算法成功的应用,而采用了简单的同时发送加密码和文本消息,并在接收方显示。

程序改进方面,一是我们的登录部分没有设置新用户的注册,只要用户名唯一,端口与IP正确即可成功登录。这会给用户登录造成混乱。另一方面,设计的解密功能没有真正实现。最后,语音功能与断点传送功能都是程序可以扩充改进的地方。

综合本次设计,我们小组严格按照设计的要求,分析应用程序开发的要点,通过资料与视频学习,从窗体设计到功能实现,最后设计实现了网络通信等功能。

8.2 XX总结 这次计算机网络课程设计,加深了我网路协议和套接字编程的了解,虽然有限,但是通过实验学习基本上能够把协议设计思想应用到现实应用中,实现一些通信功能。

这次课程设计我们是采用C#语言来编程的,虽然曾经使用过,对一些控件的使用和某些方法有一定的了解,但是由于不熟悉网络应用编程,设计过程中还是遇到不少的困难,编程过程中对一些错误总是找不出原因,或者需要花费更多的时间来修改。刚开始时对使用的一些方法的应用上也有些问题,不熟悉的情况下很可能想用其它的方法来实现,导致功能上欠缺或者产生一些冲突。

这是第一次编写基于服务端和客户端的网络程序,刚开始时总是挺疑惑:怎样才能实现逻辑连接?觉得自己很难办到。但事实是,事在人为。没有尝试永远都不知道事情的可能性到底有多大,实践总是检验问题最直接有效的方法。这次课程设计加深我对网络协议的理解的同时,也扩展了知识面。因而在今后的学习工作中,我还会多动手练习,更好的加深理解和巩固知识结构。

由于能力有限,所以有些功能还是没能实现,例如语音通话和断点重传,很想加入,但老是失败,虽然有些遗憾,但是我们在程序中加入其它功能,包括闪屏振动和界面皮肤选择,使得界面更加生动和灵活,也算是种“补偿”吧。本来是尝试建一个数据库来实现用户管理和信息存放的,但是编程过程中总是得顾虑到数据库应该如何实现,因为时间的关系也只能搁浅。

这次课程设计还有一个很大的缺点:对异常情况的考虑不足,对异常的处理不够。导致连接上一出问题就意外终止或者没法再操作,得重新启动。

9. 参考文献 [1]谢希仁.计算机网络(第五版).北京:电子工业出版社.2007.5. [2]马俊. C#网络应用编程(第二版).北京:人民邮电出版社.2010.1 [3]谭桂华,魏亮. Visual C#高级编程范例.北京:清华大学出版社.2004.4 [4]吴晨,陈建孝. C# 网络与通信程序设计案例精讲. 北京:清华大学出版社.2006.10 [5]刘瑞新.C#网络编程及应用.北京:机械工业出版社.2004.6 课程设计评分表 教师评阅:
□ 设计目的明确;
  □操作步骤正确;
  □设计文稿(表格、程序、数据库、网页)符合要求;

□ 设计结果正确;
 □设计分析总结全面;
 □设计报告规范;

课程设计答辩情况记录:
□ 思路清晰;
语言表达准确,概念清楚。

□ 准备工作充分, 具备必要的报告资料;
报告在规定的时间内完成。

□ 回答问题有理论依据,基本概念清楚。主要问题回答简明准确;
  □ 对前人工作有改进或突破,或有独特见解。

                     评阅教师签名:

Tags: 应用程序   网络通信   课程设计  

搜索
网站分类
标签列表