局域网内部聊天系统课程设计.docx
- 文档编号:8398859
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:16
- 大小:695.10KB
局域网内部聊天系统课程设计.docx
《局域网内部聊天系统课程设计.docx》由会员分享,可在线阅读,更多相关《局域网内部聊天系统课程设计.docx(16页珍藏版)》请在冰豆网上搜索。
局域网内部聊天系统课程设计
摘要
随着计算机网络技术的发展,各种各样基于网络的应用也随之诞生,比如基于互联网的信息发布,通信,数据共享等等。
局域网的发展也同样迅速。
很多政府机构,企业,学校,都是先以一个同意的局域网联结在一起,再分别接入Internet。
因此,基于局域网的即时通信工具,就这样应运而生了。
所以本文提出了一个更加合理的设计,并在Windows平台上加以了实现。
在本系统中,分别创建了客户端和服务端两个程序,用多线程实现不同的并行任务。
并进行了人性化的界面设计,使用起来更加简单方便,并且功能十分合理,又易于扩展以及个性化定制。
本文通过局域网聊天系统来具体共享内存实现进程间的数据交换,利用Windows消息机制实现进程间的同步,两种机制结合使用。
关键字:
局域网;即时通信;客户端;服务端;多线程;共享内存;信息。
目录
1课程设计目的1
2课程设计要求1
3相关知识1
4实训设计分析3
4.1体系结构设计3
4.2功能模块划分4
4.3系统流程图6
4.4用户界面设计7
5程序代码9
6运行结果与分析13
7结论14
8参考文献14
1课程设计目的
1)巩固和加深学生对C#语言课程的基本知识的理解和掌握
2)掌握C#语言编程和程序调试的基本技能
3)利用C#语言进行基本的网络软件设计
4)掌握书写程序设计说明文档的能力
5)提高运用C#语言解决实际问题的能力
2课程设计要求
1)分析课程设计题目的要求
2)写出详细设计说明
3)编写程序代码,调试程序使其能正确运行
4)设计完成的软件要便于操作和使用
5)设计完成后提交课程设计报告
3相关知识
1、TCP/IP协议[1]
通常包含了一系列与“TCP(传输控制协议)”和“IP(网际协议)”有联系的网络协议,它包括其它的协议,应用软件,甚至网络媒介。
这些协议的示例是:
UDP(UserDatagramProtocol)协议、ICMP(InternetControlMessageProtocol)协议、ARP(地址解析协议)和其他一些协议的协议组。
应用的示例:
telnet(远程登录)、ftp(文件传递协议)、http等。
2、进程及线程概述
进程和线程都是操作系统的概念。
进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。
线程是进程内部的一个执行单元。
系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main,将程序的启动点提供给Windows系统。
主执行线程终止了,进程也就随之终止。
每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。
用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。
一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。
多线程可以实现并行处理,避免了某项任务长时间占用CPU时间。
要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。
由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能。
4实训设计分析
4.1体系结构设计
通常的通信工具,都采用客户机/服务器(C/S)体系结构,C/S结构是这样的一种结构:
它包括一个客户机(或前端),一个服务器(或称后端),客户机的作用是访问和处理远程服务器上的数据,服务器的作用是接收和处理客户机的数据请求。
有时,可能有多个客户向同一个服务器同时请求服务,这就需要服务器决定怎样处理这些请求。
Client/Server结构是当前数据库应用程序中极为流行的一种方式。
尤其是网络技术的发展,使得当前很多系统都采用这种方式进行构造,其最大的优点是将计算机工作任务分别由客户端和服务器端来共同完成,这样有利于充分合理的利用系统资源。
另外它的服务器端还可以将信息集中起来,任何客户机都可以通过访问服务器而获得所需的信息。
Client/Server模型最终可归结为一种“请求/应答”关系。
一个请求总是首先被客户发出,然后服务器总是被动地接收请求,返回客户需要的结果。
在客户发出一个请求之前,服务进程一直处于休眠状态。
一个客户提出请求后,服务进程被“唤醒”并且为客户提供服务,对客户的请求做出所需要的应答[2]。
如下图所示:
图4.1客户机/服务器通信结构示图
在客户端启动后,客户端计算得到本地网络的广播地址,进行广播查找服务器端,服务器接收到客户端的广播信息后返回服务器地址,则客户端接收、验证信息并记录服务器端地址,然后客户端启动定时期,定时发送信息到服务器,以告知服务器自己在线,然后服务器返回在线用户列表,服务器依靠客户端发送的信息来更新维护在线用户列表。
在客户端与服务器尽心数据交换,拥有了在线用户列表后,就可以选择IP进行客户端之间的点对点信息交流了。
如果服务器不在线,则客户端会提示用户退出,在一定的时间后自动退出。
4.2功能模块划分
系统的功能模块划分如下图所示:
图4.2功能模块图
其中主线程模块完成对网络的初始化,然后启动两个子线程:
服务端监听线程以及网络扫描模块线程,然后由网络扫描模块得到当前的网络用户分布情况,并填充相关的数据结构,然后生成用户列表界面显示给用户。
通信模块又包括两个子模块:
数据接收模块和数据发送模块,这两个模块都由系统定义的网络事件来触发。
输入/输出模块用来响应用户单击用户列表的某一项要准备发送信息时的消息,以及当系统接收到某个网络用户发送来的消息,要将其显示给用户的时候。
网络扫描模块是由主线程模块启动,进行网络扫描,确定哪些用户当前处于可到达状态,以及哪些可到达状态的用户安装有相应的通信软件,并启动之可以与之进行通信。
4.3系统流程图
1、局域网聊天系统工作流程图
图4.3聊天系统工作流程图
2、服务器监听流程图
图4.4服务器监听流程图
3、客户信息交流模块流程图
图4.5客户信息交流流程图
4.4用户界面设计
在能够完全满足软件所需功能,设计界面要清爽、操作要简单易懂的基本原则下,本软件的界面设计如下:
服务器端显示界面如下:
图4.6服务器端界面图
客户端显示界面如下:
图4.7客户端界面图
5程序代码
1、服务器端主要程序代码如下:
///
privatevoidbuttonStart_Click(objectsender,EventArgse)
{
myListener=newTcpListener(localAddress,port);
myListener.Start();
AddItemToListBox(string.Format("开始在{0}:
{1}监听客户连接",localAddress,port));
//创建一个线程监听客户端连接请求
ThreadmyThread=newThread(ListenClientConnect);
myThread.Start();
buttonStart.Enabled=false;
buttonStop.Enabled=true;
}
///
privatevoidListenClientConnect()
{
TcpClientnewClient=null;
while(true)
{
try
{
newClient=myListener.AcceptTcpClient();
}
catch
{
//当单击“停止监听”或者退出此窗体时AcceptTcpClient()会产生异常
//因此可以利用此异常退出循环
break;
}
//每接受一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息
Useruser=newUser(newClient);
ThreadthreadReceive=newThread(ReceiveData);
threadReceive.Start(user);
userList.Add(user);
AddItemToListBox(string.Format("[{0}]进入",newClient.Client.RemoteEndPoint));
AddItemToListBox(string.Format("当前连接用户数:
{0}",userList.Count));
}
}
///
///处理接收的客户端数据
///
///
privatevoidReceiveData(objectuserState)
{
Useruser=(User)userState;
TcpClientclient=user.client;
while(isNormalExit==false)
{
stringreceiveString=null;
try
{
//从网络流中读出字符串,此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串
receiveString=user.br.ReadString();
}
catch
{
if(isNormalExit==false)
{
AddItemToListBox(string.Format("与[{0}]失去联系,已终止接收该用户信息",client.Client.RemoteEndPoint));
RemoveUser(user);
}
break;
}
AddItemToListBox(string.Format("来自[{0}]:
{1}",user.client.Client.RemoteEndPoint,receiveString));
string[]splitString=receiveString.Split(',');
switch(splitString[0])
{
case"Login":
user.userName=splitString[1];
SendToAllClient(user,receiveString);
break;
case"Logout":
SendToAllClient(user,receiveString);
RemoveUser(user);
return;
case"Talk":
stringtalkString=receiveString.Substring(splitString[0].Length+splitString[1].Length+2);
AddItemToListBox(string.Format("{0}对{1}说:
{2}",
user.userName,splitString[1],talkString));
SendToClient(user,"talk,"+user.userName+","+talkString);
foreach(UsertargetinuserList)
{
if(target.userName==splitString[1]&&user.userName!
=splitString[1])
{
SendToClient(target,"talk,"+user.userName+","+talkString);
break;
}
}
break;
default:
AddItemToListBox("什么意思啊:
"+receiveString);
break;
}
}
}
///
privatevoidbuttonStop_Click(objectsender,EventArgse)
{
AddItemToListBox("开始停止服务,并依次使用户退出!
");
isNormalExit=true;
for(inti=userList.Count-1;i>=0;i--)
{
RemoveUser(userList[i]);
}
//通过停止监听让myListener.AcceptTcpClient()产生异常退出监听线程
myListener.Stop();
buttonStart.Enabled=true;
buttonStop.Enabled=false;
}
2、客户端主要程序代码如下:
///
privatevoidbuttonConnect_Click(objectsender,EventArgse)
{
buttonConnect.Enabled=false;
try
{
//此处为方便演示,实际使用时要将Dns.GetHostName()改为服务器域名
client=newTcpClient(Dns.GetHostName(),51888);
AddTalkMessage("连接成功");
}
catch
{
AddTalkMessage("连接失败");
buttonConnect.Enabled=true;
return;
}
//获取网络流
NetworkStreamnetworkStream=client.GetStream();
//将网络流作为二进制读写对象
br=newBinaryReader(networkStream);
bw=newBinaryWriter(networkStream);
SendMessage("Login,"+textBoxUserName.Text);
ThreadthreadReceive=newThread(newThreadStart(ReceiveData));
threadReceive.IsBackground=true;
threadReceive.Start();
}
///
privatevoidReceiveData()
{
stringreceiveString=null;
while(isExit==false)
{
try
{
//从网络流中读出字符串
//此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串
receiveString=br.ReadString();
}
catch
{
if(isExit==false)
{
MessageBox.Show("与服务器失去联系。
");
}
break;
}
string[]splitString=receiveString.Split(',');
stringcommand=splitString[0].ToLower();
switch(command)
{
case"login":
//格式:
login,用户名
AddOnline(splitString[1]);
break;
case"logout":
//格式:
logout,用户名
RemoveUserName(splitString[1]);
break;
case"talk":
//格式:
talk,用户名,对话信息
//AddTalkMessage(splitString[1]+":
\r\n");
//AddTalkMessage(receiveString.Substring(
//splitString[0].Length+splitString[1].Length+2));
AddTalkMessage(string.Format("[{0}]说:
{1}",
splitString[1],receiveString.Substring(
splitString[0].Length+splitString[1].Length+2)));
break;
default:
AddTalkMessage("什么意思啊:
"+receiveString);
break;
}
}
Application.Exit();
}
///
privatevoidSendMessage(stringmessage)
{
try
{
//将字符串写入网络流,此方法会自动附加字符串长度前缀
bw.Write(message);
bw.Flush();
}
catch
{
AddTalkMessage("发送失败!
");
}
}
///
privatevoidbuttonSend_Click(objectsender,EventArgse)
{
if(listBoxOnlineStatus.SelectedIndex!
=-1)
{
SendMessage("Talk,"+listBoxOnlineStatus.SelectedItem+","+textBoxSend.Text);
textBoxSend.Clear();
}
else
{
MessageBox.Show("请先在[当前在线]中选择一个对话者");
}
}
6运行结果与分析
服务器端和客户端的初始化界面如下:
图6.1初始化界面图
两个用户相互发送消息,运行界面如下:
图6.2聊天界面图
7结论
在这次课程设计中,我们组完成了局域网内多个用户聊天的设计,编码和测试。
其中主要的功能设计,总体设计,它们都是比较重要的部分,也是后期系统设计的基础与后备。
本聊天软件能够完成了现实中局域网内多个用户之间相互发送信息,服务器能够查看所有用户之间的信息交流。
由于时间和个人水平的有限,该聊天软件的客户端仍然不完善,比如聊天界面不够美观,没有详细的个人信息管理等。
我相信随着通信技术改革的不断推进、科学技术不断的发展和社会的不断进步,通信会呈现出一幅广阔的前景,局域网内部通信的软件应用范围广阔,不但可以处理传统的通信需求,而且也能适应新型的网络应用。
8参考文献
[1]谢希仁编著.计算机网络(第5版).北京:
电子工业出版社,2008
[2]吴宜功吴英编著.计算机网络课程设计(第2版).北京:
机械工业出版社,2012
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 局域网 内部 聊天 系统 课程设计