C网络编程专题9实现类似QQ的即时通信程序

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

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

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

资源描述

C#网络编程系列]专题九:实现类似QQ的即时通信程序(转载:)引言:前面专题中介绍了UDP、TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net类库去实现它们的。为了让大家更好的理解我们平常中常见的软件QQ的工作原理,所以在本专题中将利用前面专题介绍的知识来实现一个类似QQ的聊天程序。一、即时通信系统在我们的生活中经常使用即时通信的软件,我们经常接触到的有:QQ、阿里旺旺、MSN等等。这些都是属于即时通信(InstantMessenger,IM)软件,IM是指所有能够即时发送和接收互联网消息的软件。在前面专题P2P编程中介绍过P2P系统分两种类型——单纯型P2P和混合型P2P(QQ就是属于混合型的应用),混合型P2P系统中的服务器(也叫索引服务器)起到协调的作用。在文件共享类应用中,如果采用混合型P2P技术的话,索引服务器就保存着文件信息,这样就可能会造成版权的问题,然而在即时通信类的软件中,因为客户端传递的都是简单的聊天文本而不是网络媒体资源,这样就不存在版权问题了,在这种情况下,就可以采用混合型P2P技术来实现我们的即时通信软件。前面已经讲了,腾讯的QQ就是属于混合型P2P的软件。因此,本专题要实现一个类似QQ的聊天程序,其中用到的P2P技术是属于混合型P2P,而不是前一专题中的采用的单纯型P2P技术,同时本程序的实现也会用到TCP、UDP编程技术。具体的相关内容大家可以查看本系列的相关专题的。二、程序实现的详细设计本程序采用P2P方式,各个客户端之间直接发消息进行聊天,服务器在其中只是起到协调的作用,下面先理清下程序的流程:2.1程序流程设计当一个新用户通过客户端登陆系统后,从服务器获取当在线的用户信息列表,列表信息包括系统中每个用户的地址,然后用户就可以单独向其他发消息。如果有用户加入或者在线用户退出时,服务器就会及时发消息通知系统中的所有其他客户端,达到它们即时地更新用户信息列表。根据上面大致的描述,我们可以把系统的流程分为下面几步来更好的理解(大家可以参考QQ程序将会更好的理解本程序的流程):用户通过客户端进入系统,向服务器发出消息,请求登陆服务器收到请求后,向客户端返回回应消息,表示同意接受该用户加入,并把自己(指的是服务器)所在监听的端口发送给客户端客户端根据服务器发送过来的端口号和服务器建立连接服务器通过该连接把在线用户的列表信息发送给新加入的客户端。客户端获得了在线用户列表后就可以自己选择在线用户聊天。(程序中另外设计一个类似QQ的聊天窗口来进行聊天)当用户退出系统时也要及时通知服务器,服务器再把这个消息转发给每个在线的用户,使客户端及时更新本地的用户信息列表。2.2通信协议设计所谓协议就是约定,即服务器和客户端之间会话信息的内容格式进行约定,使双方都可以识别,达到更好的通信。下面就具体介绍下协议的设计:1.客户端和服务器之间的对话(1)登陆过程①客户端用匿名UDP的方式向服务器发出下面的信息:login,username,localIPEndPoint消息内容包括三个字段,每个字段用“,”分割,login表示的是请求登陆;username表示用户名;localIPEndPint表示客户端本地地址。②服务器收到后以匿名UDP返回下面的回应:Accept,port其中Accept表示服务器接受请求,port表示服务器所在的端口号,服务器监听着这个端口的客户端连接③连接服务器,获取用户列表客户端从上一步获得了端口号,然后向该端口发起TCP连接,向服务器索取在线用户列表,服务器接受连接后将用户列表传输到客户端。用户列表信息格式如下:username1,IPEndPoint1;username2,IPEndPoint2;...;endusername1、username2表示用户名,IPEndPoint1,IPEndPoint2表示对应的端点,每个用户信息都是由用户名+端点组成,用户信息以“;”隔开,整个用户列表以“end”结尾。(2)注销过程用户退出时,向服务器发送如下消息:logout,username,localIPEndPoint这条消息看字面意思大家都知道就是告诉服务器username+localIPEndPoint这个用户要退出了。2.服务器管理用户(1)新用户加入通知因为系统中在线的每个用户都有一份当前在线用户表,因此当有新用户登录时,服务器不需要重复地给系统中的每个用户再发送所有用户信息,只需要将新加入用户的信息通知其他用户,其他用户再更新自己的用户列表。服务器向系统中每个用户广播如下信息:login,username,remoteIPEndPoint在这个过程中服务器只是负责将收到的login信息转发出去。(2)用户退出与新用户加入一样,服务器将用户退出的消息进行广播转发:logout,username,remoteIPEndPoint3.客户端之间聊天用户进行聊天时,各自的客户端之间是以P2P方式进行工作的,不与服务器有直接联系,这也是P2P技术的特点。聊天发送的消息格式如下:talk,longtime,selfUserName,message其中,talk表明这是聊天内容的消息;longtime是长时间格式的当前系统时间;selfUserName为发送发的用户名;message表示消息的内容。协议设计介绍完后,下面就进入本程序的具体实现的介绍的。注:协议是本程序的核心,也是所有软件的核心,每个软件产品的协议都是不一样的,QQ有自己的一套协议,MSN又有另一套协议,所以使用的QQ的用户无法和用MSN的朋友进行聊天。三、程序的实现服务器端核心代码:ViewCode1//启动服务器2//根据博客中协议的设计部分3//客户端先向服务器发送登录请求,然后通过服务器返回的端口号4//再与服务器建立连接5//所以启动服务按钮事件中有两个套接字:一个是接收客户端信息套接字和6//监听客户端连接套接字7privatevoidbtnStart_Click(objectsender,EventArgse)8{9//创建接收套接字10serverIp=IPAddress.Parse(txbServerIP.Text);11serverIPEndPoint=newIPEndPoint(serverIp,int.Parse(txbServerport.Text));12receiveUdpClient=newUdpClient(serverIPEndPoint);13//启动接收线程14ThreadreceiveThread=newThread(ReceiveMessage);15receiveThread.Start();16btnStart.Enabled=false;17btnStop.Enabled=true;1819//随机指定监听端口20Randomrandom=newRandom();21tcpPort=random.Next(port+1,65536);2223//创建监听套接字24tcpListener=newTcpListener(serverIp,tcpPort);25tcpListener.Start();2627//启动监听线程28ThreadlistenThread=newThread(ListenClientConnect);29listenThread.Start();30AddItemToListBox(string.Format(服务器线程{0}启动,监听端口{1},serverIPEndPoint,tcpPort));31}3233//接收客户端发来的信息34privatevoidReceiveMessage()35{36IPEndPointremoteIPEndPoint=newIPEndPoint(IPAddress.Any,0);37while(true)38{39try40{41//关闭receiveUdpClient时下面一行代码会产生异常42byte[]receiveBytes=receiveUdpClient.Receive(refremoteIPEndPoint);43stringmessage=Encoding.Unicode.GetString(receiveBytes,0,receiveBytes.Length);4445//显示消息内容46AddItemToListBox(string.Format({0}:{1},remoteIPEndPoint,message));4748//处理消息数据49//根据协议的设计部分,从客户端发送来的消息是具有一定格式的50//服务器接收消息后要对消息做处理51string[]splitstring=message.Split(',');52//解析用户端地址53string[]splitsubstring=splitstring[2].Split(':');54IPEndPointclientIPEndPoint=newIPEndPoint(IPAddress.Parse(splitsubstring[0]),int.Parse(splitsubstring[1]));55switch(splitstring[0])56{57//如果是登录信息,向客户端发送应答消息和广播有新用户登录消息58caselogin:59Useruser=newUser(splitstring[1],clientIPEndPoint);60//往在线的用户列表添加新成员61userList.Add(user);62AddItemToListBox(string.Format(用户{0}({1})加入,user.GetName(),user.GetIPEndPoint()));63stringsendString=Accept,+tcpPort.ToString();64//向客户端发送应答消息65SendtoClient(user,sendString);66AddItemToListBox(string.Format(向{0}({1})发出:[{2}],user.GetName(),user.GetIPEndPoint(),sendString));67for(inti=0;iuserList.Count;i++)68{69if(userList[i].GetName()!=user.GetName())70{71//给在线的其他用户发送广播消息72//通知有新用户加入73SendtoClient(userList[i],message);74}75}7677AddItemToListBox(string.Format(广播:[{0}],message));78break;79caselogout:80for(inti=0;iuserList.Count;i++)81{82if(userList[i].GetName()==splitstring[1])83{84AddItemToListBox(string.Format(用户{0}({1})退出,userList[i].GetName(),userList[i].GetIPEndPoint()));85userList.RemoveAt(i);//移除用户86}87}88for(inti=0;iuserList.Count;i++)89{90//广播注销消息91SendtoClient(userList[i],message);92}93AddItemToListBox(string.Format(广播:[{0}],message));94break;95}96}97catch98{99//发送异常退出循环100break;101}102}103AddItemToListBox(string.For

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

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

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

×
保存成功