c#聊天室程序Word下载.docx

上传人:b****1 文档编号:1359123 上传时间:2023-04-30 格式:DOCX 页数:22 大小:232.34KB
下载 相关 举报
c#聊天室程序Word下载.docx_第1页
第1页 / 共22页
c#聊天室程序Word下载.docx_第2页
第2页 / 共22页
c#聊天室程序Word下载.docx_第3页
第3页 / 共22页
c#聊天室程序Word下载.docx_第4页
第4页 / 共22页
c#聊天室程序Word下载.docx_第5页
第5页 / 共22页
c#聊天室程序Word下载.docx_第6页
第6页 / 共22页
c#聊天室程序Word下载.docx_第7页
第7页 / 共22页
c#聊天室程序Word下载.docx_第8页
第8页 / 共22页
c#聊天室程序Word下载.docx_第9页
第9页 / 共22页
c#聊天室程序Word下载.docx_第10页
第10页 / 共22页
c#聊天室程序Word下载.docx_第11页
第11页 / 共22页
c#聊天室程序Word下载.docx_第12页
第12页 / 共22页
c#聊天室程序Word下载.docx_第13页
第13页 / 共22页
c#聊天室程序Word下载.docx_第14页
第14页 / 共22页
c#聊天室程序Word下载.docx_第15页
第15页 / 共22页
c#聊天室程序Word下载.docx_第16页
第16页 / 共22页
c#聊天室程序Word下载.docx_第17页
第17页 / 共22页
c#聊天室程序Word下载.docx_第18页
第18页 / 共22页
c#聊天室程序Word下载.docx_第19页
第19页 / 共22页
c#聊天室程序Word下载.docx_第20页
第20页 / 共22页
亲,该文档总共22页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

c#聊天室程序Word下载.docx

《c#聊天室程序Word下载.docx》由会员分享,可在线阅读,更多相关《c#聊天室程序Word下载.docx(22页珍藏版)》请在冰点文库上搜索。

c#聊天室程序Word下载.docx

总结15

基于TCP协议的C#聊天程序

前言

随着互联网技术的飞速发展,基于网络的即时通信技术也给人们带来了诸多便利,人们也慢慢体会到了网上聊天的乐趣与无拘束的感觉。

聊天工具作为当今使用最为广泛的即时通信工具之一,可以方便的同网络上的好友在线交流。

在中国,最流行的莫过于腾讯公司的QQ,伴随着技术的不断升级,腾讯公司也为我们带来了越来越多的精彩的服务。

这里我将利用Socket编程技术模拟QQ聊天功能,实现一个简单的在线聊天室。

需求分析

1.1编写目的

编写该软件能够对自己所学的东西进行一次系统的回顾,加深对TCP协议的理解以及提升自己实际开发的能力。

1.2开发环境

操作系统:

windowsxpsp3

内存:

2G

CPU:

AMDAthlon(tm)64X2DualCoreProcessor5200+2.71GHz

编程软件:

MicrosoftVisualStudio2010

1.3功能介绍

该程序是利用c#语言编写的一个基于Socket的简单聊天软件,最要实现了用户登录,但登录时只需要提供用户名,不需要输入密码。

具有私聊和群聊两种聊天模式,即允许多人在线聊天,并且在线用户聊天时,可以将消息发送给一个用户,亦可以将消息发送给所有人。

聊天的消息内容包括:

用户名称、发送时间、发送正文、以及消息模式。

断开连接的同时会关闭客户端,此时用户若希望聊天,需要再次登录服务器。

1.4Socket通信机制

Socket编程是建立在应用层TCP/IP协议之上的。

目前最流行的是客户机/服务器模式,在面向连接的Client/Server模型中,Server端的socket总是等待一个Client端的请求。

客户机/服务器模型的工作流程图如下图所示:

服务器程序特点:

1一般启动后就一直处于运行状态,以等待客户机进程的请求;

2使用的端口往往是熟知端口,便于客户机进程连接请求;

3一般拥有较多的系统资源,以便及时响应各个客户机进程的请求;

4可以并行处理多个客户机进程的请求,但数目是有一定的限制;

5在通信时一般处于被动的一方,不需要知道客户机的IP地址和端口信息。

客户机程序的特点:

①在需要服务器进程的服务时将向服务器进程请求服务,并建立通信连接,得到满足并完成处理后就终止通信连接;

②使用向系统申请的临时端口与服务器进程进行通信,通信完成后将释放该端口;

③拥有相对较少的系统资源;

④在通信时属于主动的一方,需要事先知道服务器的IP地址和端口信息

客户机与服务器模式又分为两大类:

面向连接的交互(TCP)和面向无连接的交互(UDP),本程序是面向连接的交互,交互机制如下图:

代码实现

2.1服务器端主要代码

负责监听客户端请求,并根据客户端命令执行不同操作的Listener类,Listener.cs

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Net.Sockets;

usingSystem.Net;

usingSystem.Threading;

usingSystem.Collections.Specialized;

usingSystem.Runtime.Serialization;

usingSystem.IO;

usingSystem.Runtime.Serialization.Formatters.Binary;

namespaceTalkerServer

{

classListener

{

publicdelegatevoidShowMsg(ListenWindowlisWin,stringsvrInfo);

//svrInfo要显示的服务器信息,lisWin显示的窗口对象

privateListenWindowlisWin=null;

//服务器监听窗口对象

privateShowMsgsmsg=null;

//消息显示委托对象

privateintlistenPort=8888;

//监听端口,默认8888

privateconstintmaxPacket=64*1024;

//缓冲区大小

privateDictionary<

string,Socket>

userMap=newDictionary<

();

//所有登陆服务器的用户map

privateTcpListenertcpListener=null;

//侦听器

publicintListenPort

get{returnthis.listenPort;

}

set{this.listenPort=value;

}

publicTcpListenerTcpListener

get{returnthis.tcpListener;

set{this.tcpListener=value;

publicDictionary<

string,Socket>

UserMap

get{returnthis.userMap;

set{this.userMap=value;

publicvoidListen(ShowMsgsmsg,stringsvrInfo,ListenWindowlisWin)

this.lisWin=lisWin;

this.smsg=smsg;

stringconnInfo=string.Empty;

IPAddressipAddr=Dns.GetHostAddresses(Dns.GetHostName())[0];

tcpListener=newTcpListener(ipAddr,listenPort);

tcpListener.Start();

connInfo+="

服务器已经启动,正在监听客户端的连接……\r\n"

;

smsg(lisWin,connInfo);

while(true)

byte[]packetBuff=newbyte[maxPacket];

Socketclient=tcpListener.AcceptSocket();

client.Receive(packetBuff);

stringuserName=Encoding.Unicode.GetString(packetBuff).TrimEnd('

\0'

);

if(userMap.ContainsKey(userName)&

&

userMap.Count!

=0)

client.Send(Encoding.Unicode.GetBytes("

0"

));

//该用户存在

else

1"

//该用户不存在

userMap.Add(userName,client);

//保存客户端到Map中

stringsvrlog=string.Format("

[系统消息]新用户【{0}】在【{1}】已连接...当前在线人数:

【{2}】\r\n\r\n"

userName,DateTime.Now,userMap.Count);

smsg(lisWin,svrlog);

//利用委托更新服务器显示日志

ThreadclientThread=newThread(newParameterizedThreadStart(ThreadFunc));

//开启一个子线程执行程序

clientThread.Start(userName);

foreach(KeyValuePair<

userinuserMap)

stringuName=user.Keyasstring;

SocketclientSkt=user.ValueasSocket;

if(!

uName.Equals(userName))

clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));

//序列化在线用户列表

privatebyte[]SerializeOnlineUserList(Objectobj)

StringCollectiononlineUserList=newStringCollection();

foreach(objectoinuserMap.Keys)

if(o!

=obj)//序列化的在线列表中不包含自身登陆用户

onlineUserList.Add(oasstring);

//转换语句

IFormatterformat=newBinaryFormatter();

//以二进制格式将对象或整个连接对

MemoryStreamstream=newMemoryStream();

format.Serialize(stream,onlineUserList);

//保持到内存流

byte[]ret=stream.ToArray();

stream.Close();

returnret;

publicvoidThreadFunc(Objectobj)

Socketclient=null;

stringuserName=(string)obj;

if(userMap.TryGetValue(userName,outclient))

if(client!

=null)

try

byte[]_cmdBuff=newbyte[128];

client.Receive(_cmdBuff);

//第一次接收命令,第二次接收内容

string_cmd=string.Concat(_cmdBuff[0].ToString(),_cmdBuff[1].ToString());

//00对所有人,01请求用户列表,02断开连接

if(_cmd=="

00"

byte[]_msgBuff=newbyte[maxPacket];

client.Receive(_msgBuff);

foreach(KeyValuePair<

clientSkt.Send(_msgBuff);

elseif(_cmd=="

01"

)//请求用户列表

byte[]onlineBuff=SerializeOnlineUserList(obj);

//先发送响应信号,用于客户机的判断,"

11"

表示服务发给客户机的更新在线列表的命令

client.Send(newbyte[]{1,1});

client.Send(onlineBuff);

02"

)//与服务器断开连接

userMap.Remove(userName);

[系统消息]用户【{0}】在【{1}】已断开...当前在线人数:

//给其他用户通知现在上线的用户

Thread.CurrentThread.Abort();

//终止为该客户端开启的线程

else//发送给指定用户

string_receiver=Encoding.Unicode.GetString(_cmdBuff).TrimEnd('

byte[]_packetBuff=newbyte[maxPacket];

client.Receive(_packetBuff);

if(userMap.ContainsKey(_receiver))//是否存在该接收者

//通过转发表查找接收方的套接字

SocketreceiverSkt=userMap[_receiver]asSocket;

receiverSkt.Send(_packetBuff);

stringsysMessage=string.Format("

[系统消息]您刚才的内容没有发送成功。

\r\n可能原因:

用户【{0}】已离线或者网络阻塞。

\r\n\r\n"

_receiver);

client.Send(Encoding.Unicode.GetBytes(sysMessage));

catch(SocketException)

[系统消息]用户【{0}】的客户端在【{1}】意外终止!

当前在线人数【{2}】\r\n\r\n"

//向所有客户机发送系统消息

负责显示客户端连接信息的服务器窗口的后台处理代码:

usingSystem.ComponentModel;

usingSystem.Data;

usingSystem.Drawing;

usingSystem.Windows.Forms;

{

publicpartialclassListenWindow:

Form

privateListenerlistener=null;

privateThreadlistenThread=null;

delegatevoidSetTextCallback(ListenWindowlisWin,stringtext);

publicListenWindow()

InitializeComponent();

listener=newListener();

privatevoidbtnListen_Click(objectsender,EventArgse)

this.btnListen.Enabled=false;

intport=this.listener.ListenPort;

if(int.TryParse(txtEndpoint.Text,outport))

if(port<

1024||port>

65535)

MessageBox.Show("

端口号不合法!

"

"

提示"

MessageBoxButtons.OK,MessageBoxIcon.Information);

return;

this.listenThread=newThread(newThreadStart(this.ThreadProcSafe));

this.listenThread.Start();

"

MessageBoxButtons.OK,MessageBoxIcon.Information);

publicvoidshowSvgMsg(ListenWindowlisWin,stringsvrInfo)

lisWin.txtConnInfo.Text=svrInfo;

#region

///<

summary>

///1:

访问Windows窗体控件本质上不是线程安全的。

///2:

如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。

///3:

如果从创建控件的线程之外的其他线程试图更改控件的状态,一半情况下是不行的

///4:

以事件句柄创建一个以线程安全方式调用windows窗体控件的线程。

/summary>

publicvoidThreadProcSafe()//线程安全访问控件

this.listener.Listen(SetText,"

this);

privatevoidSetText(ListenWindowlisWin,stringtext)

if(lisWin.txtConnInfo.InvokeRequired)

SetTextCallbackd=newSetTextCallback(SetText);

lisWin.Invoke(d,newobject[]{this,text});

lisWin.txtConnInfo.AppendText(text);

#endregion

privatevoidbtnStopListen_Click(objectsender,EventArgse)

if(listener!

if(listener.TcpListener!

listener.TcpListener.Stop();

if(listener.UserMap.Count!

foreach(Socketsocketinlistener.UserMap.Values)

socket.Shutdown(SocketShutdown.Both);

listener.UserMap.Clear();

listener.UserMap=null;

listener=null;

this.btnListen.Enabled=true;

2.2客户端主要代码

客户端聊天窗口后台代码:

namespaceTalkClient

publicpartialclassTalkWindow:

privatestring_username=null;

//登陆用户名

privateintmaxPacket=2048;

//2K的缓冲区

privateThreadreceiveThread=null;

//用于接收消息

privateNetworkStream_nws=null;

//网络数据流

delegatevoidSetTextCallback(TalkWindowtalkWin,stringtext);

///处理接收到的消息

privatevoidMsgHandle()

while(true)//无限循环,不断接收消息

byte[]packet=newbyte[maxPacket];

_nws.Read(packet,0,pa

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2