windows课程设计.doc_第1页
windows课程设计.doc_第2页
windows课程设计.doc_第3页
windows课程设计.doc_第4页
windows课程设计.doc_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

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

文档简介

目 录一. 需求分析21.1 开发背景21.2 功能要求21.3 运行环境21.4 功能实现2二项目设计32.1程序流图32.2 概要设计32.3功能设计42.4 详细设计62.4.1界面设计6客户端82.4.2程序结构设计12三、代码实现.123.1、客户端123.2服务器端16四、 项目测试22五、总结:22六、参考文献 .23 一. 需求分析1.1 开发背景在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,类似QQ、网络聊天时一类的聊天系统的发展日新月异。但是,QQ等现有的聊天程序也存在着很大的问题。比如,我在使用QQ的时候,就对他发的各种“广告”深恶痛绝。对于登陆后时不时弹出的打扰窗口,很是厌烦。因此我在本次作业的激励下,产生了一个制作类似QQ的网络聊天工具并且“无垃圾信息”洁净聊天工具的想法,而且希望通过制作该程序还能更好的学习网络软件编程知识。1.2 功能要求(1)登录功能。(2)客户可以通过服务器转发,实现一对一、一对多和多对多聊天。(3)实现文件传输。(4)服务器端和客户端程序都能实时显示在线用户数目。1.3 运行环境 本系统基于WINDOWS socket接口设计,适用于WINDOWS XP等系统。 1.4 功能实现1登录验证功能。对于账号重复等异常,需要提示给用户。2. 客户通过服务器转发,实现一对一、一对多和多对多聊天。3. 实时显示目前其它用户的状态,能够提示在线用户数目、状态等。4. 保存并能察看聊天纪录。5申请新的用户号码。6. 易用、美观的图形界面,实现系统托盘。7. 传输文件可以选择不同的用户。二项目设计2.1程序流图22 概要设计通过C#,实现网络聊天的功能,采用Windows Socket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。由于服务器端要保存用户信息,我们利用数据库来实现这一功能,因此首先需要建立用户信息数据库。在客户端保存聊天纪录和用户号码这一功能的实现中,采用了文件系统设计。在传输文件时,采用tcp连接。2.3功能设计客户端:1) 登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。2) 界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。3) 聊天功能:与好友聊天。4) 聊天纪录:能保存聊天纪录,并能察看聊天纪录。5) 文件传输:能相互传送文件。登陆到服务器客户端申请新的号码显示在线用户接收各种信息保存用户号码保存聊天纪录服务器端:向各个客户端发布系统消息。接受来自客户端的各种信息并分别处理。1) 登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。2) 聊天信息:转发给消息指定的用户。3) 申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。4) 用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。服务器端处理申请信息转发聊天信息处理登陆信息发布系统消息程序中主要变量及函数的功能说明如下:客户端:private void login_btn_Click(object sender, EventArgs e) - 登陆到服务器 private void svrip_tb_TextChanged(object sender,EventArgs e)设置要连接的服务器的地址端口private void chatrcd_rtb_TextChanged(object sender, EventArgs e)- 显示好友发送的信息private void send_btn_Click(object sender, EventArgs e) - 给好友发送信息private void user_tb_TextChanged(object sender, EventArgs e) - 申请新的用户private void chatrcd_rtb_TextChanged(object sender, EventArgs e) - 显示服务器消息private void msg_tb_TextChanged(object sender, EventArgs e) - 显示消息输入文本 private void btnSelect_Click(object sender, EventArgs e)-进行文件传输服务器端:用户及发送信息结构体类型:public void StartUp()-服务器启动,并且实时更新用户在线信息public void GetConfig()-配置服务器端口号等信息void WatchConncecting()-持续不断的监听新的客服端的请求private void ThreadFunc(object obj)-系统对于发送消息、发送抖动等的异常的处理public void Close()-关闭服务器private void btnSelect_Click(object sender, EventArgs e)-进行文件传输24 详细设计2.4.1主界面设计主界面窗体运行后如图1.1所示,通过ListView控件和ImageList显示在线的人物以及选择聊天对象,通过StatusStrip控件显示在线人数以及包括“上线”和“下线”功能。 图1.1设计步骤: 1. 添加控件和组件在解决方案资源管理器中打开“Form1.cs”。将Form1窗体调整到适当大小,从工具箱中拖放1个“NotifyIcon”组件、1个“ListView”和1个“ImageList”控件到此窗体中。参考图1.1所示摆放控件。 2. 设置窗体和控件组件的属性Form1的Text属性值设置为“聊天室”,Icon设置为已经准备好的图标,MaximizeBox设置为“False”。(1)notifyIcon1的属性设置。Icon选择已经准备好的图标,Text设置为“聊天室”。(2)imageList1的属性设置。(3)listView1的属性设置。打开listView1属性窗口,FullRowSelect和View属性值分别设置为“True”和“Title”,MultiSelect设置为“False”,StateImageList属性选择为“imageList1”,Columns集合中分别添加3个“columnHeader”成员。(4)statusStrip1的设置。分别添加一个“toolStripStatusLabel”和一个“toolStripDropDownButton”。toolStripStatusLabel1的Text属性设置为“在线人数 人”,选中toolStripDropDownButton1Text,分别添加“上线”和“下线”选项, 3. 添加事件及代码主窗口窗体包含有、“选择聊天对象”和“调整大小”事件。(1)添加命名空间。因为涉及线程和网络的操作,所以添加命名空间如下:using System.Threading;using System.Net;using System.Net.Sockets;(2)添加字段。所添加的字段如下所示:private UdpClient UdpListen = new UdpClient(8000);private IPAddress myIP = Dns.GetHostEntry(Dns.GetHostName().AddressList0;/本机器IP地址private string myName = Environment.UserName; /本机器用户名/*标识网络地址,初始化广播端口号*/private IPEndPoint EndPoint = new IPEndPoint(IPAddress.Parse(55), 8000);private static bool MyState = false;/是否为在线状态(3)主界面中添加上线人的成员方法。通过数据包参数将此上线的人的用户名、IP地址以及图像显示在主界面中,并更新在线人数。代码如下:private void AddPerson(DataPacket dp) /添加聊天的人 ListViewItem lviUserName = new ListViewItem(); ListViewItem.ListViewSubItem lvsiComputerName = new ListViewItem.ListViewSubItem(); ListViewItem.ListViewSubItem lvsiIP = new ListViewItem.ListViewSubItem(); lvsiComputerName.Text = dp.ComputerName; lvsiIP.Text = dp.FromIP.ToString(); (4)监听指定端口的广播地址UDP包的成员方法的代码。当接受到数据包时,分析其包的命令,并执行相应的代码。(5)添加“窗体加载”事件及其代码。当窗体加载时就开启监听线程,切换到Form1的设计视图,双击窗体,添加代码,代码如下所示:public Form1() InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false;/关闭对文本框的跨线程操作检查 Thread threadWatch = null;/负责监听客服端连接请求的线程 Socket socketWatch = null;/负责监听的套接字 private void btnBeginListen_Click(object sender, EventArgs e) try /创建负责监听的套接字,参数(使用IPV4,流式连接,TCP传输协议 socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /获取文本框中的IP地址对象 IPAddress address = IPAddress.Parse(txtIp.Text.Trim(); /创建包含IP和PORT的网络节点对象 IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim(); /将负责监听的套接字绑定到唯一的IP和PORT上 socketWatch.Bind(endpoint); /设置监听队列的长度 socketWatch.Listen(10); /创建负责监听的线程并传入监听方法 threadWatch = new Thread(WatchConncecting);。(6)添加选中聊天对象事件及其代码。当双击聊天对象时弹出聊天窗口并发生聊天请求数据包。在listView1的事件窗口中双击DoubleClick,添加其事件代码,代码如下:private void btnSend_Click(object sender, EventArgs e) if (txtMsgSend.Text.Trim() = ) MessageBox.Show(发送内容不能为空!); else if (string.IsNullOrEmpty(lbOnline.Text) MessageBox.Show(请选择要发送的好友!); else string strMsg = txtMsgSend.Text.Trim(); byte arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg); byte arrMsgSend = new bytearrMsg.Length + 1; arrMsgSend0 = 0;/代表发送文字 Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length); string clientKey = lbOnline.Text; try dictclientKey.Send(arrMsgSend); dictclientKey.Send(arrMsg); ShowMsg(我说: + strMsg); txtMsgSend.Clear(); catch (SocketException ex) ShowMsg(发送时异常: + ex.Message); return; catch (Exception ex) ShowMsg(发送时异常: + ex.Message); return; /sokConnection.Send(arrMsg); 4. 运行程序客户端1) 登陆界面2) 显示当前状态3) 最小化到托盘4) 发送接收消息 5) 发送文件服务端1) 服务器启动配置端口号2.4.2程序结构设计如概要设计反映。三代码实现3.1、客户端namespace Socket聊天程序Client public partial class Form1 : Form public Form1() InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; Thread threadClient = null; Socket socketClient = null; private void btnBeginListen_Click(object sender, EventArgs e) IPAddress address = IPAddress.Parse(txtIp.Text.Trim(); IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim(); socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try socketClient.Connect(endpoint); threadClient = new Thread(RecMsg); threadClient.IsBackground = true; threadClient.Start(); MessageBox.Show(连接服务器成功!); catch MessageBox.Show(远程服务器没开启,连接失败!,提示,MessageBoxButtons.OK,MessageBoxIcon.Warning); void RecMsg() while (true) byte arrMsgRec = new byte1024 * 1024 * 2; int length = -1; try length = socketClient.Receive(arrMsgRec); catch (SocketException ex) ShowMsg( ex.Message); break; catch (Exception ex) ShowMsg(ex.Message); break; if (arrMsgRec0 = 0) string msgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length - 1); ShowMsg(msgRec); else if (arrMsgRec0 = 1) SaveFileDialog file = new SaveFileDialog(); if (file.ShowDialog() = System.Windows.Forms.DialogResult.OK) string fileSavePath = file.FileName; using (FileStream fs = new FileStream(fileSavePath, FileMode.Create) fs.Write(arrMsgRec, 1, length - 1); ShowMsg(文件保存成功: + fileSavePath); void ShowMsg(string msg) txtMsg.AppendText(msg + rn); private void btnSend_Click(object sender, EventArgs e) if (txtSend.Text.Trim() = ) MessageBox.Show(发送内容不能为空!); else string strMsg = txtSend.Text.Trim(); byte arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg); byte arrMsgSend = new bytearrMsg.Length + 1; arrMsgSend0 = 0;/代表发送文字 Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length); try socketClient.Send(arrMsgSend); ShowMsg(我说: + strMsg); txtSend.Clear(); catch MessageBox.Show(客户端未连接到服务器); private void btnSelect_Click(object sender, EventArgs e) OpenFileDialog file = new OpenFileDialog(); if (file.ShowDialog() = System.Windows.Forms.DialogResult.OK) txtFile.Text = file.FileName; private void btnFileSend_Click(object sender, EventArgs e) if (txtFile.Text = ) MessageBox.Show(发送文件路径不能为空!); else try using (FileStream fs = new FileStream(txtFile.Text, FileMode.Open) byte arrFile = new byte1024 * 1024 * 2; int length = fs.Read(arrFile, 0, arrFile.Length); byte arrFileSend = new bytelength + 1; arrFileSend0 = 1;/代表发送的是文件数据 /for (int i = 0; i length; i+) / / arrFileSendi + 1 = arrFilei; / Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length); socketClient.Send(arrFileSend); catch MessageBox.Show(客户端未连接到服务器); 3.2服务器端namespace Socket聊天程序Server public partial class Form1 : Form public Form1() InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false;/关闭对文本框的跨线程操作检查 Thread threadWatch = null;/负责监听客服端连接请求的线程 Socket socketWatch = null;/负责监听的套接字 private void btnBeginListen_Click(object sender, EventArgs e) try /创建负责监听的套接字,参数(使用IPV4,流式连接,TCP传输协议 socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /获取文本框中的IP地址对象 IPAddress address = IPAddress.Parse(txtIp.Text.Trim(); /创建包含IP和PORT的网络节点对象 IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim(); /将负责监听的套接字绑定到唯一的IP和PORT上 socketWatch.Bind(endpoint); /设置监听队列的长度 socketWatch.Listen(10); /创建负责监听的线程并传入监听方法 threadWatch = new Thread(WatchConncecting); threadWatch.IsBackground = true;/设置后台线程 threadWatch.Start();/开启线程 ShowMsg(服务器启动成功!); catch(SocketException ex) MessageBox.Show(ex.Message,错误,MessageBoxButtons.OK,MessageBoxIcon.Error); Dictionary dict = new Dictionary(); Dictionary dictThred = new Dictionary(); / / 服务端负责监听客服端发送过来的数据的方法 / void RecMsg(object sockClientPara) Socket socketClient = sockClientPara as Socket; while (true) byte arrMsgRec = new byte1024 * 1024 * 2; int length = 2; try length = socketClient.Receive(arrMsgRec); if (arrMsgRec0 = 0) try string msgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length - 1); ShowMsg(msgRec); catch ShowMsg(socketClient.RemoteEndPoint.ToString()+断开连接); dict.Remove(socketClient.RemoteEndPoint.ToString(); dictThred.Remove(socketClient.RemoteEndPoint.ToString(); lbOnline.Items.Remove(socketClient.RemoteEndPoint.ToString(); break; else if (arrMsgRec0 = 1) SaveFileDialog file = new SaveFileDialog(); if (file.ShowDialog() = System.Windows.Forms.DialogResult.OK) string fileSavePath = file.FileName; using (FileStream fs = new FileStream(fileSavePath, FileMode.Create) fs.Write(arrMsgRec, 1, length - 1); ShowMsg(文件保存成功: + fileSavePath); catch (SocketException ex) ShowMsg(ex.Message); dict.Remove(socketClient.RemoteEndPoint.ToString(); dictThred.Remove(socketClient.RemoteEndPoint.ToString(); lbOnline.Items.Remove(socketClient.RemoteEndPoint.ToString(); break; catch (Exception ex) ShowMsg(ex.Message); dict.Remove(socketClient.RemoteEndPoint.ToString(); dictThred.Remove(socketClient.RemoteEndPoint.ToString(); lbOnline.Items.Remove(socketClient.RemoteEndPoint.ToString(); break; / / 监听客服端请求的方法 / void WatchConncecting() while (true)/持续不断的监听新的客服端的请求 /开始监听客服端连接请求,注意:Accept方法,会阻断当前线程 Socket sokConnection = socketWatch.Accept();/一旦监听到客服端请求,就返回一个负责和该客服端通信的套接字sokConnection lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString(); dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection); /创建通信线程 Thread thr = new Thread(RecMsg); thr.IsBackground = true; thr.Start(sokConnection); dictThred.Add(sokConnection.RemoteEndPoint.ToString(), thr); ShowMsg(sokConnection.RemoteEndPoint.ToString() + 连接到服务器!); void ShowMsg(string msg) txtMsg.AppendText(msg + rn); private void btnSend_Click(object sender, EventArgs e) if (txtMsgSend.Text.Trim() = ) MessageBox.Show(发送内容不能为空!); else if (string.IsNullOrEmpty(lbOnline.T

温馨提示

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

评论

0/150

提交评论