基于Socket的聊天室(C#版)(共25页)

上传人:94****0 文档编号:59101474 上传时间:2022-03-01 格式:DOC 页数:26 大小:966KB
收藏 版权申诉 举报 下载
基于Socket的聊天室(C#版)(共25页)_第1页
第1页 / 共26页
基于Socket的聊天室(C#版)(共25页)_第2页
第2页 / 共26页
基于Socket的聊天室(C#版)(共25页)_第3页
第3页 / 共26页
资源描述:

《基于Socket的聊天室(C#版)(共25页)》由会员分享,可在线阅读,更多相关《基于Socket的聊天室(C#版)(共25页)(26页珍藏版)》请在装配图网上搜索。

1、精选优质文档-倾情为你奉上一、服务器/客户端聊天室模型1.首先启动聊天室服务器,使得TcpListener开始监听端口,此时TcpListener会进入Pending状态,等待客户端连接;2.其次,当有客户端连接后,通过AccepSocket返回与客户端连接的Socket对象,然后通过读写Socket对象完成与聊天室客户端的数据传输。聊天室客户端成功启动后,首先创建一个Socket对象,然后通过这个Socket对象连接聊天室服务器,连接成功后开通Socket完成数据的接收和发送处理。二、系统功能设计本设计为一个简单的聊天室工具,设计基本的聊天功能,如聊天、列表维护等。系统主要为两大块:聊天室服

2、务器及聊天室客户端。服务器界面设计如下:客户端界面设计如下:三、聊天协议的应答A网络B主机与主机通信主要识别身份(标识设备用IP)及通信协议网络应用程序端口号接收数据注:1.IP地址是总机,端口号是分机(传输层)2.端口号为16位二进制数,范围0到65535,但实际编程只能用1024以上端口号Socket编程首先,我们了解常用网络编程协议。我们用得最多的协议是UDP和TCP,UDP是不可靠传输服务,TCP是可靠传输服务。UDP就像点对点的数据传输一样,发送者把数据打包,包上有收信者的地址和其他必要信息,至于收信者能不能收到,UDP协议并不保证。而TCP协议就像(实际他们是一个层次的网络协议)是

3、建立在UDP的基础上,加入了校验和重传等复杂的机制来保证数据可靠的传达到收信者。一个是面向连接一个无连接,各有用处,在一些数据传输率高的场合如视频会议倾向于UDP,而对一些数据安全要求高的地方如下载文件就倾向于TCP。Socket网络应用程序电话机访问通信协议聊天协议的应答:聊天状态:CLOSED和CONNECTED状态执行CONN命令后进入CONNECTED状态,执行下列命令:CONN:连接聊天室服务器JOIN:加入聊天(通知其他用户本人已经加入聊天室服务器)LIST:列出所有的用户(向客户端发送全部的登录用户名字)CHAT:发送聊天信息(公开的聊天信息)PRIV:进行私聊(三个参数:私聊信

4、息用户;接收私聊信息用户;发送信息)EXIT:客户端向服务器发送离开请求;QUIT:退出聊天,服务器向客户端发送退出命令(执行QUIT命令聊天状态变为CLOSED)四、系统实现服务器协议解析:当有客户端连接聊天室服务器后,服务器立刻为这个客户建立一个数据接收的线程(多用户程序必备)。在接收线程中,如果收到聊天命令,就对其进行解析处理,服务器可以处理五种命令:CONNLISTCHATPRIVEXIT。服务器接收到CONN命令,就向其他用户发送JOIN命令告诉有用户加入,然后把当前的全部用户信息返回给刚刚加入的用户,以便在界面上显示用户列表。当接收到EXIT命令后,就清除当前用户的信息,然后向其他

5、用户发送QUIT命令,告诉其他用户退出了,这些用户的客户端把离开的用户从用户列表中删除。聊天室客户端的协议解析:当客户端连接到服务器后,服务器立刻建立一个数据接收的独立线程。在接收线程中,如果收到了聊天命令,就对其进行解析处理。聊天室客户端一共处理的命令有五种:OKERRLISTJOINQUIT命令。五、程序设计(代码)服务器端设计:引入网络操作命名空间System.Net、System.Net.Sockets;线程处理命名空间System.Threading第一步:界面设计及类与相关成员的定义对界面进行设计(简单)对内部函数进行设计(要编写一个独立的类即Client类,封装了客户端的信息与连

6、接,每一个客户进入聊天室,就创建一个Client对象,用于保存该用户的信息并接收用户数据和发送信息到客户端)几个重要的类:TcpListener类(服务器套接字创建)、Socket类internal static Hashtable clients = new Hashtable();/clients数组保存当前在线用户的client对象 private TcpListener listener;/该服务器默认的监听端口号 static int MAX_NUM = 100; /服务器可以支持的客户端的最大连接数 internal static bool SocketServiceFlag =

7、false;/开始服务的标志/获得本地局域网或者拨号动态分配的IP地址,在启动服务器时会用到IP地址 private string getIPAddress() /获得本机局域网IP地址 IPAddress Addresslist=Dns.GetHostEntry(Dns.GetHostName().AddressList; if (Addresslist.Length1) return ; return Addresslist0.ToString(); /获得动态的IP地址 private static string getDynamicIPAddress() IPAddress Addre

8、sslist = Dns.GetHostEntry(Dns.GetHostName().AddressList; if (Addresslist.Length 2) return ; return Addresslist1.ToString(); /服务器监听的端口号通过getValidPort()函数获得 private int getValidPort(string port) int lport; /测试端口号是否有效 try /是否为空 if (port = ) throw new ArgumentException(端口号为空,不能启动服务器); lport = System.Con

9、vert.ToInt32(port); catch (Exception e) Console.WriteLine(无效的端口号: + e.ToString(); this.rtbSocketMsg.AppendText(无效的端口号: + e.ToString() + n); return -1; return lport; private void btnSocketStart_Click(object sender, EventArgs e) int port = getValidPort(tbSocketPort.Text); if (port = MAX_NUM) this.rtbS

10、ocketMsg.AppendText(已经达到了最大连接数: + MAX_NUM + ,拒绝新的链接n); socket.Close(); else /启动一个新的线程 /执行方法this.ServiceClient,处理用户相应的请求 ChatSever.Client.Client client = new ChatSever.Client.Client(this, socket); Thread clientService = new Thread(new ThreadStart(client.ServiceClient); clientService.Start(); Thread.S

11、leep(200);/提高性能整体速度,原因不详 catch (Exception ex) this.rtbSocketMsg.AppendText(ex.Message.ToString() + n); private void tbSocketPort_TextChanged(object sender, EventArgs e) if (this.tbSocketPort.Text!=) this.btnSocketStart.Enabled = true; /下面为一些界面处理函数 private void btnSocketStop_Click(object sender, Even

12、tArgs e) Form1.SocketServiceFlag = false; this.btnSocketStart.Enabled = true; this.btnSocketStop.Enabled = false; public void addUser(string username) this.rtbSocketMsg.AppendText(username + 已经加入n);/将刚连接的用户名加入到当前在线用户列表中 this.lbSocketClients.Items.Add(username); this.tbSocketClientsNum.Text = System.

13、Convert.ToString(clients.Count); public void removeUser(string username) this.rtbSocketMsg.AppendText(username + 已经离开n);/将刚连接的用户名加入到当前在线用户列表中 this.lbSocketClients.Items.Remove(username); this.tbSocketClientsNum.Text = System.Convert.ToString(clients.Count); public string GetUserList() string Rtn = ;

14、 for (int i = 0; i lbSocketClients.Items.Count; i+) Rtn += lbSocketClients.Itemsi.ToString() + |; return Rtn; public void updateUI(string msg) this.rtbSocketMsg.AppendText(msg + n); private void Form1_FormClosing(object sender, FormClosingEventArgs e) Form1.SocketServiceFlag = false; /下面为Client类定义pu

15、blic class Client private string name;/保存用户名 private Socket currentSocket = null;/保存与当前用户连接的Socket对象 private string ipAddress;/保存用户的IP地址 private Form1 server; /保存当前连接状态 /Closed-connected-closed private string state = closed; public Client(Form1 server, Socket clientSocket) this.server = server; this

16、.currentSocket = clientSocket; ipAddress = getRemoteIPAddress(); public string Name get return name; set name = value; public Socket CurrentSocket get return currentSocket;/ipAddress private string getRemoteIPAddress() return (IPEndPoint)currentSocket.RemoteEndPoint).Address.ToString(); /SendToClien

17、t()方法实现了向客户端发送命令请求的功能 private void SendToClient(Client client, string msg) System.Byte message = System.Text.Encoding.Default.GetBytes(msg.ToCharArray(); client.currentSocket.Send(message, message.Length, 0); /ServiceClient 方法用于和客户端进行数据通信,包括接收客户端的请求 /它根据不同的请求命令执行相应的操作,并将处理结果返回到客户端 /ServiceClient()函数

18、为服务器接收客户数据的线程主体,主要用来接收用户发送来的数据,并处理聊天命令 public void ServiceClient() string tokens=null; byte buff=new byte1024; bool keepConnect=true; /用循环来不断地与客户端进行交互,直到客户端发出“EXIT”命令 /将keepConnect职为false,退出循环,关闭连接,并中止当前线程 while(keepConnect&Form1.SocketServiceFlag) /tokens=null; try if(currentSocket=null|currentSock

19、et.Available+receiver+”:”+content; /仅将信息转发给法送者和接收者 if (Form1.clients.Contains(sender) SendToClient(Client)Form1.clientssender,message); if (Form1.clients.Contains(receiver) SendToClient(Client)Form1.clientsreceiver,message); server.updateUI(tokens1); else /send err to server SendToClient(this,ERR|st

20、ate error,please login first); else if (tokens0=EXIT) /此时收到的命令的格式为:命令标识符EXIT|发送者的用户名:发送内容| /向所有当前在线的用户发送该用户已离开的消息 if(Form1.clients.Contains(tokens1) Client client=(Client)Form1.clients(tokens1); /将该用户对应Client对象从clients中删除 Hashtable syncClients=Hashtable.Synchronized(Form1.clients); syncClients.Remov

21、e(client.name); server.removeUser(client.name); /向客户端发送QUIT命令 string message =QUIT|+tokens1; System.Collections.IEnumerator myEnumerator=Form1.clients.Values.GetEnumerator(); while(myEnumerator.MoveNext() Client c =(Client)myEnumerator.Current; /将发送者的用户名:发送内容 转发给用户 SendToClient(c,message); server.up

22、dateUI(QUIT); /退出当前线程 break; Thread.Sleep(200); 客户端设计:包含一个类ChatClientForm,该类封装了聊天室客户端界面和聊天命令处理逻辑。其中一个重要的类TcpClient类(用于与服务器的连接)TcpClient tcpClient; /与服务器的链接 private NetworkStream Stream;/与服务器数据交互的流通道 private static string CLOSED = closed; private static string CONNECTED = connected; private string st

23、ate = CLOSED; private bool stopFlag; private Color color;/保存当前客户端显示的颜色 /连接聊天室服务器/通过TcpClient方法连接聊天室服务器并发送CONN消息命令 private void btnLogin_Click_1(object sender, EventArgs e) if (state = CONNECTED) return; if (this.tbUserName.TextLength = 0) MessageBox.Show(请输入您的昵称!, 提示信息, MessageBoxButtons.OK, Message

24、BoxIcon.Exclamation); this.tbUserName.Focus();/为控件设置焦点,人性化设计 return; try /创建一个客户端套接字,它是Login的一个公共属性 tcpClient = new TcpClient();/将被传递给ChatClient窗体 tcpClient.Connect(IPAddress.Parse(txtHost.Text), Int32.Parse(txtPort.Text);/向指定的IP地址服务器发出连接请求 Stream = tcpClient.GetStream(); /获得与服务器数据交互的流通道 NetworksStr

25、eam /启动一个新的线程,执行方法this.ServerResponse(),以便来响应从服务器发回的信息 Thread thread1 = new Thread(new ThreadStart(this.ServerResponse); thread1.Start(); /向服务器发送CONN请求命令 /此命令的格式与服务器端的定义的格式一致 /命令格式为:命令标志符CONN|发送者的用户名 string cmd = CONN| + this.tbUserName.Text + |; /将字符串转化为字符数组 Byte outbytes = System.Text.Encoding.Def

26、ault.GetBytes(cmd.ToCharArray(); Stream.Write(outbytes, 0, outbytes.Length); catch (Exception ex) MessageBox.Show(ex.Message); private void btnSend_Click_1(object sender, EventArgs e) try if (!this.cbPrivate.Checked) /此时命令的格式是:命令标识符CHAT|发送者的用户名:发送内容| string message = CHAT| + this.tbUserName.Text + :

27、 + tbSendContent.Text; tbSendContent.Text = ; tbSendContent.Focus(); byte outbytes = System.Text.Encoding.Default.GetBytes(message.ToCharArray(); /将字符串转化为字符数组 Stream.Write(outbytes, 0, outbytes.Length); else if (lstUsers.SelectedIndex = -1) MessageBox.Show(请在列表中选择一个用户, 提示信息, MessageBoxButtons.OK, Me

28、ssageBoxIcon.Exclamation); return; string receiver = lstUsers.SelectedItem.ToString(); /消息的格式是:命令标识符PRIV|发送者的用户名|接收者的用户名|发送内容 string message = PRIV| + this.tbUserName.Text + | + receiver + | + tbSendContent.Text + |; tbSendContent.Text = ; tbSendContent.Focus(); byte outbytes = System.Text.Encoding.

29、Default.GetBytes(message.ToCharArray(); /将字符串转化为字符数组 Stream.Write(outbytes, 0, outbytes.Length); catch this.rtbMsg.AppendText(网络发生错误!); /this.ServerResponse()方法用于接收从服务器发回的信息,根据不同的命令,执行相应的操作 private void ServerResponse() /定义一个byte数组,用于接收从服务器端发来的数据 /每次所能接受的数据包的最大长度为1024个字节 byte buff = new byte1024; string msg; int len; try if (Stream.CanRead=false) return; stopFlag = false; while (!stopFlag) /从流中得到数据,并存入到buff字符数组中 len = Stream.Read(buff, 0, buff.Length); if (len 1) Thread.Sleep(200); continue;

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!