![c#聊天室程序_第1页](http://file4.renrendoc.com/view/27c8632944001176d7d0ad991faf45c0/27c8632944001176d7d0ad991faf45c01.gif)
![c#聊天室程序_第2页](http://file4.renrendoc.com/view/27c8632944001176d7d0ad991faf45c0/27c8632944001176d7d0ad991faf45c02.gif)
![c#聊天室程序_第3页](http://file4.renrendoc.com/view/27c8632944001176d7d0ad991faf45c0/27c8632944001176d7d0ad991faf45c03.gif)
![c#聊天室程序_第4页](http://file4.renrendoc.com/view/27c8632944001176d7d0ad991faf45c0/27c8632944001176d7d0ad991faf45c04.gif)
![c#聊天室程序_第5页](http://file4.renrendoc.com/view/27c8632944001176d7d0ad991faf45c0/27c8632944001176d7d0ad991faf45c05.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、精选优质文档-倾情为你奉上精选优质文档-倾情为你奉上专心-专注-专业专心-专注-专业精选优质文档-倾情为你奉上专心-专注-专业计算机学院课程设计专 业: 08网络工程 课程名称: TCP/IP协议分析实验 课题名称: 基于TCP协议的C#聊天程序 教 师: 桂学勤 学 号: 时 间: 2010 年 6月 18日目录 TOC o 1-3 h z u 基于TCP协议的C#聊天程序前言随着互联网技术的飞速发展,基于网络的即时通信技术也给人们带来了诸多便利,人们也慢慢体会到了网上聊天的乐趣与无拘束的感觉。聊天工具作为当今使用最为广泛的即时通信工具之一,可以方便的同网络上的好友在线交流。在中国,最流行的
2、莫过于腾讯公司的QQ,伴随着技术的不断升级,腾讯公司也为我们带来了越来越多的精彩的服务。这里我将利用Socket编程技术模拟QQ聊天功能,实现一个简单的在线聊天室。一:需求分析1.1编写目的编写该软件能够对自己所学的东西进行一次系统的回顾,加深对TCP协议的理解以及提升自己实际开发的能力。1.2开发环境操作系统:windows xp sp3内存:2GCPU:AMD Athlon(tm) 64 X2 Dual Core Processor 5200+ 2.71GHz编程软件:Microsoft Visual Studio 20101.3功能介绍该程序是利用c#语言编写的一个基于Socket的简单
3、聊天软件,最要实现了用户登录,但登录时只需要提供用户名,不需要输入密码。具有私聊和群聊两种聊天模式,即允许多人在线聊天,并且在线用户聊天时,可以将消息发送给一个用户,亦可以将消息发送给所有人。聊天的消息内容包括:用户名称、发送时间、发送正文、以及消息模式。断开连接的同时会关闭客户端,此时用户若希望聊天,需要再次登录服务器。1.4Socket通信机制Socket编程是建立在应用层TCP/IP协议之上的。目前最流行的是客户机/服务器模式,在面向连接的 Client/Server 模型中,Server 端的 socket 总是等待一个 Client 端的请求。客户机/服务器模型的工作流程图如下图所示
4、:服务器程序特点:一般启动后就一直处于运行状态,以等待客户机进程的请求;使用的端口往往是熟知端口,便于客户机进程连接请求;一般拥有较多的系统资源,以便及时响应各个客户机进程的请求;可以并行处理多个客户机进程的请求,但数目是有一定的限制;在通信时一般处于被动的一方,不需要知道客户机的IP地址和端口信息。客户机程序的特点: 在需要服务器进程的服务时将向服务器进程请求服务,并建立通信连接,得到满足并完成处理后就终止通信连接; 使用向系统申请的临时端口与服务器进程进行通信,通信完成后将释放该端口; 拥有相对较少的系统资源; 在通信时属于主动的一方,需要事先知道服务器的IP地址和端口信息客户机与服务器模
5、式又分为两大类:面向连接的交互(TCP)和面向无连接的交互(UDP),本程序是面向连接的交互,交互机制如下图:二:代码实现2.1服务器端主要代码负责监听客户端请求,并根据客户端命令执行不同操作的Listener类,Listener.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Sockets;using System.Net;using System.Threading;using System.Collections.Specialize
6、d;using System.Runtime.Serialization;using System.IO;using System.Runtime.Serialization.Formatters.Binary;namespace TalkerServer class Listener public delegate void ShowMsg(ListenWindow lisWin, string svrInfo);/svrInfo要显示的服务器信息,lisWin显示的窗口对象 private ListenWindow lisWin = null;/服务器监听窗口对象 private Show
7、Msg smsg = null;/消息显示委托对象 private int listenPort = 8888;/监听端口,默认8888 private const int maxPacket = 64 * 1024;/缓冲区大小 private Dictionary userMap = new Dictionary();/所有登陆服务器的用户map private TcpListener tcpListener = null;/侦听器 public int ListenPort get return this.listenPort; set this.listenPort = value;
8、public TcpListener TcpListener get return this.tcpListener; set this.tcpListener = value; public Dictionary UserMap get return this.userMap; set this.userMap = value; public void Listen(ShowMsg smsg,string svrInfo,ListenWindow lisWin) this.lisWin = lisWin; this.smsg = smsg; string connInfo = string.
9、Empty; IPAddress ipAddr = Dns.GetHostAddresses(Dns.GetHostName()0; tcpListener = new TcpListener(ipAddr,listenPort); tcpListener.Start(); connInfo += 服务器已经启动,正在监听客户端的连接rn; smsg(lisWin, connInfo); while (true) byte packetBuff = new bytemaxPacket; Socket client = tcpListener.AcceptSocket(); client.Rec
10、eive(packetBuff); string userName = Encoding.Unicode.GetString(packetBuff).TrimEnd(0); if (userMap.ContainsKey(userName) & userMap.Count != 0) client.Send(Encoding.Unicode.GetBytes(0);/该用户存在 else client.Send(Encoding.Unicode.GetBytes(1);/该用户不存在 userMap.Add(userName,client);/保存客户端到Map中 string svrlog
11、= string.Format(系统消息新用户【0】在【1】已连接. 当前在线人数:【2】rnrn, userName, DateTime.Now, userMap.Count); smsg(lisWin, svrlog);/利用委托更新服务器显示日志 Thread clientThread = new Thread(new ParameterizedThreadStart(ThreadFunc);/开启一个子线程执行程序 clientThread.Start(userName); foreach(KeyValuePair user in userMap) string uName = use
12、r.Key as string; Socket clientSkt = user.Value as Socket; if (!uName.Equals(userName) clientSkt.Send(Encoding.Unicode.GetBytes(svrlog); /序列化在线用户列表 private byte SerializeOnlineUserList(Object obj) StringCollection onlineUserList = new StringCollection(); foreach (object o in userMap.Keys) if (o != ob
13、j)/序列化的在线列表中不包含自身登陆用户 onlineUserList.Add(o as string);/转换语句 IFormatter format = new BinaryFormatter();/以二进制格式将对象或整个连接对 MemoryStream stream = new MemoryStream(); format.Serialize(stream, onlineUserList);/保持到内存流 byte ret = stream.ToArray(); stream.Close(); return ret; public void ThreadFunc(Object obj
14、) Socket client = null; string userName = (string)obj; if (userMap.TryGetValue(userName, out client) if (client != null) while (true) try byte _cmdBuff = new byte128; client.Receive(_cmdBuff);/第一次接收命令,第二次接收内容 string _cmd = string.Concat(_cmdBuff0.ToString(), _cmdBuff1.ToString(); /00对所有人,01请求用户列表,02
15、断开连接 if (_cmd = 00) byte _msgBuff = new bytemaxPacket; client.Receive(_msgBuff); foreach (KeyValuePair user in userMap) string uName = user.Key as string; Socket clientSkt = user.Value as Socket; if (!uName.Equals(userName) clientSkt.Send(_msgBuff); else if (_cmd = 01)/请求用户列表 byte onlineBuff = Seria
16、lizeOnlineUserList(obj); /先发送响应信号,用于客户机的判断,11表示服务发给客户机的更新在线列表的命令 client.Send(new byte 1, 1 ); client.Send(onlineBuff); else if (_cmd = 02)/与服务器断开连接 userMap.Remove(userName); string svrlog = string.Format(系统消息用户【0】在【1】已断开. 当前在线人数:【2】rnrn, userName, DateTime.Now, userMap.Count); foreach (KeyValuePair
17、user in userMap) string uName = user.Key as string; Socket clientSkt = user.Value as Socket; clientSkt.Send(Encoding.Unicode.GetBytes(svrlog);/给其他用户通知现在上线的用户 smsg(lisWin, svrlog);/利用委托更新服务器显示日志 Thread.CurrentThread.Abort();/终止为该客户端开启的线程 else/发送给指定用户 string _receiver = Encoding.Unicode.GetString(_cmd
18、Buff).TrimEnd(0); byte _packetBuff = new bytemaxPacket; client.Receive(_packetBuff); if (userMap.ContainsKey(_receiver)/是否存在该接收者 /通过转发表查找接收方的套接字 Socket receiverSkt = userMap_receiver as Socket; receiverSkt.Send(_packetBuff); else string sysMessage = string.Format(系统消息您刚才的内容没有发送成功。rn可能原因:用户【0】已离线或者网络
19、阻塞。rnrn, _receiver); client.Send(Encoding.Unicode.GetBytes(sysMessage); catch (SocketException) string svrlog = string.Format(系统消息用户【0】的客户端在【1】意外终止!当前在线人数【2】rnrn, userName, DateTime.Now, userMap.Count); smsg(lisWin, svrlog);/利用委托更新服务器显示日志 /向所有客户机发送系统消息 foreach (KeyValuePair user in userMap) string u
20、Name = user.Key as string; Socket clientSkt = user.Value as Socket; clientSkt.Send(Encoding.Unicode.GetBytes(svrlog); Thread.CurrentThread.Abort(); 负责显示客户端连接信息的服务器窗口的后台处理代码:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.L
21、inq;using System.Text;using System.Windows.Forms;using System.Threading;using System.Net.Sockets;namespace TalkerServer public partial class ListenWindow : Form private Listener listener = null; private Thread listenThread = null; delegate void SetTextCallback(ListenWindow lisWin,string text); publi
22、c ListenWindow() InitializeComponent(); listener = new Listener(); private void btnListen_Click(object sender, EventArgs e) this.btnListen.Enabled = false; int port = this.listener.ListenPort ; if (int.TryParse(txtEndpoint.Text, out port) if (port 65535) MessageBox.Show(端口号不合法!, 提示, MessageBoxButton
23、s.OK, MessageBoxIcon.Information); return; this.listenThread = new Thread(new ThreadStart(this.ThreadProcSafe); this.listenThread.Start(); else MessageBox.Show(端口号不合法!,提示,MessageBoxButtons.OK,MessageBoxIcon.Information); return; public void showSvgMsg(ListenWindow lisWin ,string svrInfo) lisWin.txtC
24、onnInfo.Text = svrInfo; #region / / 1:访问 Windows 窗体控件本质上不是线程安全的。 / 2:如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。 / 3:如果从创建控件的线程之外的其他线程试图更改控件的状态,一半情况下是不行的 / 4:以事件句柄创建一个以线程安全方式调用windows窗体控件的线程。 / public void ThreadProcSafe()/线程安全访问控件 this.listener.Listen(SetText,this); private void SetText(ListenWindow l
25、isWin,string text) if (lisWin.txtConnInfo.InvokeRequired) SetTextCallback d = new SetTextCallback(SetText); lisWin.Invoke(d, new object this,text ); else lisWin.txtConnInfo.AppendText(text); #endregion private void btnStopListen_Click(object sender, EventArgs e) if (listener != null) if (listener.Tc
26、pListener != null) listener.TcpListener.Stop(); if (listener.UserMap.Count != 0) foreach (Socket socket in listener.UserMap.Values) socket.Shutdown(SocketShutdown.Both); listener.UserMap.Clear(); listener.UserMap = null; listener = null; this.btnListen.Enabled = true; 2.2客户端主要代码客户端聊天窗口后台代码:using Sys
27、tem;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Net.Sockets;using System.Threading;using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Bina
28、ry;using System.IO;using System.Collections.Specialized;namespace TalkClient public partial class TalkWindow : Form private string _username = null;/登陆用户名 private int maxPacket = 2048;/2K的缓冲区 private Thread receiveThread = null;/用于接收消息 private NetworkStream _nws = null;/网络数据流 delegate void SetTextCa
29、llback(TalkWindow talkWin, string text); / / 处理接收到的消息 / private void MsgHandle() while (true)/无限循环,不断接收消息 byte packet = new bytemaxPacket; _nws.Read(packet, 0, packet.Length); string msg = string.Concat(packet0.ToString(), packet1.ToString(); if (msg = 11)/更新在线用户列表 byte onlineBuff = new bytemaxPacke
30、t; int byteCnt = _nws.Read(onlineBuff, 0, onlineBuff.Length); IFormatter format = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); stream.Write(onlineBuff, 0, byteCnt); stream.Position = 0; StringCollection onlineList = (StringCollection)format.Deserialize(stream); drpReceiver.Items.
31、Clear(); foreach (string onliner in onlineList) if (!onliner.Equals(_username) drpReceiver.Items.Add(onliner); else string displaytxt = Encoding.Unicode.GetString(packet); SetText(this,displaytxt);/添加到聊天内容中 / / 从非创建该控件的线程访问该控件,并且修改其Text属性 / / / public void SetText(TalkWindow talkWin, string text) if
32、 (this.txtAllMsg.InvokeRequired) SetTextCallback stc = new SetTextCallback(SetText); talkWin.Invoke(stc, new object this,text ); else this.txtAllMsg.AppendText(text); private void btnSend_Click(object sender, EventArgs e) string localTxt = ;/本地显示消息 string remoteTxt = ;/其它用户显示的消息 string msg = txtSelf
33、Msg.Text.Trim();/本人将要发送的消息 if (msg = string.Empty) MessageBox.Show(不能发送空消息,提示,MessageBoxButtons.OK,MessageBoxIcon.Information); return; /判断选择的聊天模式 if (drpTalkModem.SelectedIndex = 0)/悄悄话模式 string receiver = drpReceiver.Text; if (receiver = string.Empty) MessageBox.Show(请选择发送悄悄话的人,若列表中为空,表明当前只有你一人在线!
34、, 提示, MessageBoxButtons.OK, MessageBoxIcon.Information); return; else localTxt = string.Format(私聊您在 0 对 1 说:rn2rnrn, DateTime.Now, receiver, msg); remoteTxt = string.Format(私聊0 在 1 对您说:rn2rnrn, _username, DateTime.Now, msg); _nws.Write(Encoding.Unicode.GetBytes(receiver), 0, Encoding.Unicode.GetByte
35、s(receiver).Length); else localTxt = string.Format(群聊您在 0 对所有人说:rn1rnrn, DateTime.Now, msg); remoteTxt = string.Format(群聊0 在 1 对所有人说:rn2rnrn, _username, DateTime.Now, msg); _nws.Write(new byte 0, 0 , 0, 2); _nws.Write(Encoding.Unicode.GetBytes(remoteTxt), 0, Encoding.Unicode.GetBytes(remoteTxt).Length); txtAllMsg.AppendText(localTxt);/添加发送的消息到聊天记录里 txtSelfMsg.Clear();/清空刚编辑发送的消息 / / 聊天模式,选择悄悄话,左边的在线用户列表可用,可以选择里面的任意用户进行聊天 / 选择所有人,消息将会群发给所有人 / / / private void drpTalkModem_SelectedIndexChanged(object sender, Ev
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 深圳市出租房屋合同书(28篇)
- 湖南信息职业技术学院2024年单招考试职业技能测试E组样题
- 设计方案优化函
- 2025年信贷调整协商协议
- 2025年医院合同管理策略与优化措施
- 2025年互联网电商员工保密协议规范
- 2025年猎头项目立项申请报告模范
- 2025年二手住宅带阁楼出售合同规范
- 2025年烟胶项目立项申请报告模稿
- 2025年二手房合同纠纷隐患与预防
- 红色中国风2025灵蛇贺岁
- 教师校园食品安全培训
- 烈士褒扬课件教学课件
- 公务用车分时租赁实施方案
- 《论语》原文-翻译-完整版
- 中医适宜技术-中药热奄包
- 压疮的预防和护理
- 《手卫生知识培训》培训课件
- 算力时代全光网架构研究报告(2024年)
- 2024年江苏省淮安市中考英语试题卷(含答案解析)
- 2025届高考作文素材:《黑神话 悟空》高考作文和素材运用
评论
0/150
提交评论