郑州轻工业学院实训报告实训名称:网络聊天程序指导教师:姓名:学号:班级:提交日期:1.实训目的通过开发一款网络聊天程序,熟练掌握多线程编程技术和TCP应用编程技术。通过本实训,应达到如下目标:理解委托的概念,掌握线程之间通过委托与控件交互的方法。理解异常处理的机制,掌握异常处理语句的用法。理解线程的概念,掌握多线程编程的一般方法。掌握基于TCP的应用编程技术。2.实训题目使用C#编程语言,开发一款网络聊天程序,玩家通过客户端登陆远程的服务器,登陆成功后可以与其他在线的玩家通信,如下图所示。3.功能描述1.管理员可以启动停止服务器,服务器可以显示当前的在线人数。2.玩家可以登陆服务器;登录后的玩家可以与其它在线的玩家聊天;在线玩家关闭客户端即退出登录。3.用户可以注册账号登陆服务器,注册即可实现永久登陆。4.需求分析根据功能描述可知,网络聊天程序的系统结构图如下所示。玩家客户端用户用户接服务器端用户集通信接管理员用户接5.设计说明服务器界面如下:客户端的登陆界面如下:客户端的注册界面如下:客户端的聊天窗口如下:6.源代码6.1服务器端User类在Server_541307110114项目中添加User类。User类的代码如下:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Net.Sockets;usingSystem.IO;namespaceServer_541307110114{publicclassUser{publicstringuserName;publicTcpClientclient;publicBinaryReaderbReader;publicBinaryWriterbWriter;publicUser(TcpClientclient){this.client=client;NetworkStreamns=client.GetStream();bReader=newBinaryReader(ns);bWriter=newBinaryWriter(ns);}publicvoidClose(){bReader.Close();bWriter.Close();client.Close();}publicvoidSend(stringmessage){try{bWriter.Write(message);bWriter.Flush();}catch(Exceptionex){throwex;}}publicstringReceive(){try{returnbReader.ReadString();}catch(Exception){throw;}}}}UserList类在项目中添加UserList类。UserList类的代码如下:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceServer_541307110114{publicclassUserList{publicListUserlist;publicUserList(){list=newListUser();}publicvoidAddUser(Useruser){list.Add(user);}publicvoidRemoveUser(Useruser){user.Close();list.Remove(user);}publicvoidRemoveAllUser(){for(inti=list.Count-1;i=0;i--){RemoveUser(list[i]);}}publicvoidSendToAllUser(Useruser,stringstr)//给所有人发消息{string[]split=str.Split(',');//把接收的字符串分离if(split[0]==login)//判断是否为新登陆{foreach(Useruinlist)//如果为新登陆,从用户集合获取每一个登陆用户{u.Send(str);//给每个用户发送新用户登陆的消息u.Send(login,+u.userName);if(u.userName!=split[1]){user.Send(login,+u.userName);//不会给自己发送}}}else{foreach(Useruinlist)//如果不是新用户登陆信息,则给除自己外每个用户发送消息{if(u.userName!=split[1]){u.Send(str);}}}}publicvoidgetAllName(Useruser){foreach(Useruinlist){if(user==u){continue;}user.Send(getAllName,+u.userName);}}}}MainWindow代码:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Data;usingSystem.Windows.Documents;usingSystem.Windows.Input;usingSystem.Windows.Media;usingSystem.Windows.Media.Imaging;usingSystem.Windows.Navigation;usingSystem.Windows.Shapes;usingSystem.Net.Sockets;usingSystem.Net;usingSystem.IO;namespaceServer_541307110114{///summary///MainWindow.xaml的交互逻辑////summarypublicpartialclassMainWindow:Window{publicTcpListenerlistener;publicUserListuserList;publicintport;publicboolisExit;publicintonlineUser;publicMainWindow(){InitializeComponent();port=1005;listener=newTcpListener(IPAddress.Any,port);//绑定IP端口号用于侦听userList=newUserList();isExit=true;onlineUser=0;btnStop.IsEnabled=false;}privatevoidbtnStart_Click(objectsender,RoutedEventArgse){listener.Start();//开始侦听isExit=false;Task.Run(()=ConnectListen());//启动侦听连接线程btnStart.IsEnabled=false;btnStop.IsEnabled=true;}publicvoidConnectListen()//用于侦听来自客户端的连接请求{while(!isExit){TcpClientclient;try{client=listener.AcceptTcpClient();//接受连接请求,连接成功}catch(Exception){break;//如有异常跳出侦听}UsernewUser=newUser(client);userList.AddUser(newUser);Task.Run(()=Receive(newUser));}}publicvoidReceive(Useruser){stringmessage=null;while(!isExit){try{message=user.Receive();}catch(Exception){}string[]split=message.Split(',');switch(split[0]){caselogin:string[]readText=ReadUserInfo();boolisLeagle=true;foreach(stringuserInfoTextinreadText){string[]str=userInfoText.Split(',');//用逗号分隔获取到的每行用户数据if(split[1]==str[0]&&split[2]==str[1])//将用户输入与此行的用户名密码对比,为真则登陆成功{foreach(UseruinuserList.list){if(u.userName==split[1])//检测该用户是否已经登陆{isLeagle=false;break;}}if(isLeagle)//如果没登陆,添加进用户列表{user.userName=split[1];userList.SendToAllUser(user,message);onlineUser++;onlineShow.Dispatcher.Invoke(()=onlineShow.Text=当前在线用户数:+onlineUser);break;}else//如果已登陆,发送sorry{user.Send(sorry);userList.RemoveUser(user);}}}if(isLeagle==false)//判断用户信息文本中是否有该用户,如果没有,发送sorry{user.Send(sorry);userList.RemoveUser(user);}break;caseregister:boolisSame=false;string[]readUserName=ReadUserInfo();foreach(stringuserInfoTextinreadUserName)//循环查找用户信息是否有重名{string[]str=userInfoText.Split(',');if(str[0]==split[1]){user.Send(regsorry);isSame=true;break;//如果有重名,跳出循环}else{continue;}}if(!isSame)//循环结束没有重名可以添加进去{vara=AppDomain.CurrentDomain;File.AppendAllText(a.BaseDirectory+@UserInfo.txt,split[1]+,+split[2]+\n,Encoding.Default);user.Send(isregister);}break;casetalk:stringreceiver=split[2];foreach(UseruinuserList.list){if(u.userName==receiver){u.Send(message);}}user.Send(message);break;caselogout:userList.SendToAllUser(user,message);userList.RemoveUser(user);onlineUser--;onlineShow.Dispatcher.Invoke(()=onlineShow.Text=当前在线用户数:+onlineUser);break;casegetAllName:userList.getAllName(user);break;default:break;}}}privatestring[]ReadUserInfo(){v