基于.Socket的聊天室(C#版)

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

--..--word可编辑.一、服务器/客户端聊天室模型聊天室客户端(商用PC)服务器聊天室客户端(其他)聊天室客户端(笔记本)其他服务器1.首先启动聊天室服务器,使得TcpListener开始监听端口,此时TcpListener会进入Pending状态,等待客户端连接;2.其次,当有客户端连接后,通过AccepSocket返回与客户端连接的Socket对象,然后通过读写Socket对象完成与聊天室客户端的数据传输。聊天室客户端成功启动后,首先创建一个Socket对象,然后通过这个Socket对象连接聊天室服务器,连接成功后开通Socket完成数据的接收和发送处理。二、系统功能设计本设计为一个简单的聊天室工具,设计基本的聊天功能,如聊天、列表维护等。系统主要为两大块:聊天室服务器及聊天室客户端。服务器界面设计如下:--..--word可编辑.客户端界面设计如下:--..--word可编辑.三、聊天协议的应答--..--word可编辑.A—网络—B主机与主机通信主要识别身份(标识设备用IP)及通信协议网络应用程序——端口号——接收数据注:1.IP地址是总机,端口号是分机(传输层)2.端口号为16位二进制数,范围0到65535,但实际编程只能用1024以上端口号Socket编程首先,我们了解常用网络编程协议。我们用得最多的协议是UDP和TCP,UDP是不可靠传输服务,TCP是可靠传输服务。UDP就像点对点的数据传输一样,发送者把数据打包,包上有收信者的地址和其他必要信息,至于收信者能不能--..--word可编辑.收到,UDP协议并不保证。而TCP协议就像(实际他们是一个层次的网络协议)是建立在UDP的基础上,加入了校验和重传等复杂的机制来保证数据可靠的传达到收信者。一个是面向连接一个无连接,各有用处,在一些数据传输率高的场合如视频会议倾向于UDP,而对一些数据安全要求高的地方如下载文件就倾向于TCP。Socket————网络应用程序电话机————访问通信协议聊天协议的应答:客户端服务器聊天命令OK/ERR应答信号聊天状态:CLOSED和CONNECTED状态执行CONN命令后进入CONNECTED状态,执行下列命令:CONN:连接聊天室服务器JOIN:加入聊天(通知其他用户本人已经加入聊天室服务器)LIST:列出所有的用户(向客户端发送全部的登录用户名字)CHAT:发送聊天信息(公开的聊天信息)PRIV:进行私聊(三个参数:私聊信息用户;接收私聊信息用户;发送信息)EXIT:客户端向服务器发送离开请求;--..--word可编辑.QUIT:退出聊天,服务器向客户端发送退出命令(执行QUIT命令聊天状态变为CLOSED)四、系统实现服务器协议解析:当有客户端连接聊天室服务器后,服务器立刻为这个客户建立一个数据接收的线程(多用户程序必备)。在接收线程中,如果收到聊天命令,就对其进行解析处理,服务器可以处理五种命令:CONN\LIST\CHAT\PRIV\EXIT。服务器接收到CONN命令,就向其他用户发送JOIN命令告诉有用户加入,然后把当前的全部用户信息返回给刚刚加入的用户,以便在界面上显示用户列表。当接收到EXIT命令后,就清除当前用户的信息,然后向其他用户发送QUIT命令,告诉其他用户退出了,这些用户的客户端把离开的用户从用户列表中删除。--..--word可编辑.启动聊天服务器启动监听器等待接收客户端连接启动客户数据接收线程保持连接并且SocketServiceFlag为true?退出线程读取数据解析命令CONN命令CHAT命令LIST命令EXIT命令PRIV命令向全部用户发送JOIN命令向当用户发送LIST命令向当用户发送LIST命令向当用户发送CHAT命令向接收者发送数据向发送者发送数据向全部用户发送QUIT命令删除用户数据休息200毫秒聊天室客户端的协议解析:当客户端连接到服务器后,服务器立刻建立一个数据接收的独立线程。在接收线程中,如果收到了聊天命令,就对其进行解析处理。聊天室客户端一共处理的命令有五种:OK\ERR\LIST\JOIN\QUIT命令。--..--word可编辑.SocketConnect启动客户数据接收线程是停止标志吗?退出线程读取数据解析命令OK命令LIST命令ERR命令QUIT命令JOIN命令命令执行成功命令执行失败显示全部用户显示用户加入显示用户离开删除用户数据休息200毫秒启动聊天室客户端NoYes其他情况直接显示用户信息五、程序设计(代码)服务器端设计:引入网络操作命名空间System.Net、System.Net.Sockets;线程处理命名空间System.Threading第一步:界面设计及类与相关成员的定义对界面进行设计(简单)--..--word可编辑.对内部函数进行设计(要编写一个独立的类即Client类,封装了客户端的信息与连接,每一个客户进入聊天室,就创建一个Client对象,用于保存该用户的信息并接收用户数据和发送信息到客户端)几个重要的类:TcpListener类(服务器套接字创建)、Socket类internalstaticHashtableclients=newHashtable();//clients数组保存当前在线用户的client对象privateTcpListenerlistener;//该服务器默认的监听端口号staticintMAX_NUM=100;//服务器可以支持的客户端的最大连接数internalstaticboolSocketServiceFlag=false;//开始服务的标志//获得本地局域网或者拨号动态分配的IP地址,在启动服务器时会用到IP地址privatestringgetIPAddress(){//获得本机局域网IP地址IPAddress[]Addresslist=Dns.GetHostEntry(Dns.GetHostName()).AddressList;if(Addresslist.Length1){return;}returnAddresslist[0].ToString();}//获得动态的IP地址privatestaticstringgetDynamicIPAddress(){IPAddress[]Addresslist=Dns.GetHostEntry(Dns.GetHostName()).AddressList;if(Addresslist.Length2){return;}returnAddresslist[1].ToString();}//服务器监听的端口号通过getValidPort()函数获得privateintgetValidPort(stringport){intlport;//测试端口号是否有效try{--..--word可编辑.//是否为空if(port==){thrownewArgumentException(端口号为空,不能启动服务器);}lport=System.Convert.ToInt32(port);}catch(Exceptione){Console.WriteLine(无效的端口号:+e.ToString());this.rtbSocketMsg.AppendText(无效的端口号:+e.ToString()+\n);return-1;}returnlport;}privatevoidbtnSocketStart_Click(objectsender,EventArgse){intport=getValidPort(tbSocketPort.Text);if(port0){return;}stringip=this.getIPAddress();try{IPAddressipAdd=IPAddress.Parse(ip);listener=newTcpListener(ipAdd,port);//创建服务器套接字listener.Start();//开始监听服务器端口this.rtbSocketMsg.AppendText(Socket服务器已经启动,正在监听+ip+端口号:+this.tbSocketPort.Text+\n);//启动一个新的线程,执行方法this.StartSocketListen,//以便在一个独立的进程中执行确认与客户端Socket连接的操作Form1.SocketServiceFlag=true;Threadthread=newThread(newThreadStart(this.StartSocketListen));thread.Start();this.btnSocketStart.Enabled=false;this.btnSocketStop.Enabled=true;}catch(Exceptionex){this.rtbSocketMsg.AppendText(ex.Message.ToString()+\n);}}--..--word可编辑.//在新的线程中的操作,它主要用于当接收到一个客户端请求时,确认与客户端的链接//并且立刻启动一个新的线程来处理和该客户端的信息交互privatevoidStartSocketListen(){while(Form1.SocketServiceFlag){try{//当接收到一个客户端请求时,确认与客户端的链接if(listener.Pending())//确认是否有挂起的连接请求{Socketsocket=listener.AcceptSocket();//接收挂起的连接请求if(clients.Count=MAX_NUM){this.rtbSocketMsg.AppendText(已经达到了最大连接数:+MAX_NUM+,拒绝新的链接\n);socket.Close();}else{//启动一个新的线程//执行方法this.ServiceClient,处理用户相应的请求ChatSever.Client.Clientclient=newChatSever.Client.Client(this,socket);ThreadclientService=newThread(newThreadStart(client.ServiceClient));clientService.Start();}}Thread.Sleep(200);//提高性能整体速度,原因不详}catch(Exceptionex){this.rtbSocketMsg.AppendText(ex.Message.ToString()+\n);}}}privatevoidtbSocketPort_TextChanged(objectsender,EventArgse){if(this.tbSocketPort.Text!=){this.btnSocketStart.Enabled=true;}}--..--word可编辑.//下面为一些界面处理函数privatevoidbtnSocketStop_Click(objectsender,EventArgse){Form1.SocketServiceFlag=false;this.btnSocketStart.Enabled=true;this.btnSocketStop.Enabled=false;}publicvoidaddUser(stringusername){this.rtbSocketMsg.AppendText(username+已经加入\n);//将刚连接的用户名加入到当前在线用户列表中this.lbSocketClients.Items.Add(username);this.tbSocketClientsNum.Text=System.Convert.ToString(clients.Count);}publicvoidremoveUser(stringusername){this.rtbSocketMsg.AppendText(username+已经离开\n

1 / 29
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功