[C# 网络编程系列]专题九:实现类似QQ的即时通信程序
转自:http://www.cnblogs.com/zhili/archive/2012/09/23/2666987.html
引言:
前面专题中介绍了UDP、TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net类库去实现它们的。为了让大家更好的理解我们平常中常见的软件QQ的工作原理,所以在本专题中将利用前面专题介绍的知识来实现一个类似QQ的聊天程序。
一、即时通信系统
在我们的生活中经常使用即时通信的软件,我们经常接触到的有:QQ、阿里旺旺、MSN等等。这些都是属于即时通信(Instant Messenger,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;...;end
username1、username2表示用户名,IPEndPoint1,IPEndPoint2表示对应的端点,每个用户信息都是由"用户名+端点"组成,用户信息以“;”隔开,整个用户列表以“end”结尾。
(2)注销过程
用户退出时,向服务器发送如下消息:
logout,username,localIPEndPoint
这条消息看字面意思大家都知道就是告诉服务器 username+localIPEndPoint这个用户要退出了。
2. 服务器管理用户
(1)新用户加入通知
因为系统中在线的每个用户都有一份当前在线用户表,因此当有新用户登录时,服务器不需要重复地给系统中的每个用户再发送所有用户信息,只需要将新加入用户的信息通知其他用户,其他用户再更新自己的用户列表。
服务器向系统中每个用户广播如下信息:
login,username,remoteIPEndPoint
在这个过程中服务器只是负责将收到的"login"信息转发出去。
(2)用户退出
与新用户加入一样,服务器将用户退出的消息进行广播转发:
logout,username,remoteIPEndPoint
3. 客户端之间聊天
用户进行聊天时,各自的客户端之间是以P2P方式进行工作的,不与服务器有直接联系,这也是P2P技术的特点。
聊天发送的消息格式如下:
talk, longtime, selfUserName, message
其中,talk表明这是聊天内容的消息;longtime是长时间格式的当前系统时间;selfUserName为发送发的用户名;message表示消息的内容。
协议设计介绍完后,下面就进入本程序的具体实现的介绍的。
注:协议是本程序的核心,也是所有软件的核心,每个软件产品的协议都是不一样的,QQ有自己的一套协议,MSN又有另一套协议,所以使用的QQ的用户无法和用MSN的朋友进行聊天。
三、程序的实现
服务器端核心代码:
客户端核心代码:
程序的运行结果:
首先先运行服务器窗口,在服务器窗口点击“启动”按钮来启动服务器,然后客户端首先指定服务器的端口号,修改用户名(这里也可以不修改,使用默认的也可以),然后点击“登录”按钮来登陆服务器(也就是告诉服务器本地的客户端地址),然后从服务器端获得在线用户列表,界面演示如下:

然后用户可以双击在线用户进行聊天(此程序支持与多人进行聊天),下面是功能的演示图片:

双方进行聊天时,这里没有实现像QQ一样,有人发信息来在对应的客户端就有消息提醒的功能的, 所以双方进行聊天的过程中,每个客户端都需要在在线用户列表中点击聊天的对象来激活聊天对话框(意思就是从图片中可以看出“天涯”客户端想和剑痴聊天的话,就在“在线用户”列表双击剑痴来激活聊天窗口,同时“剑痴”客户端也必须双击“天涯”来激活聊天窗口,这样双方就看到对方发来的信息了,(不激活窗口,也是发送了信息,只是没有一个窗口来进行显示)),而且从图片中也可以看出——此程序支持与多人聊天,即天涯同时与“剑痴”和"大地"同时聊天。
四、总结
本专题介绍了如何去实现一个类似QQ的聊天程序,一方面让大家可以巩固前面专题的内容,另一方面让大家更好的理解即时通信软件(腾讯QQ)的工作原理和软件协议的设计。
后面一专题将介绍如何去实现邮件系统中常用的功能——实现一个简单的邮件应用。
本程序的源代码链接:http://files.cnblogs.com/zhili/IM.zip 觉得有帮助的话还望推荐下,如果有任何意见可以留言。谢谢大家的支持
[C# 网络编程系列]专题九:实现类似QQ的即时通信程序的更多相关文章
- 详解C# 网络编程系列:实现类似QQ的即时通信程序
https://www.jb51.net/article/101289.htm 引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net ...
- 转:【专题九】实现类似QQ的即时通信程序
引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net类库去实现它们的.为了让大家更好的理解我们平常中常见的软件QQ的工作原理,所以在 ...
- 专题九:实现类似QQ的即时通信程序
引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net类库去实现它们的.为了让大家更好的理解我们平常中常见的软件QQ的工作原理,所以在 ...
- 实现类似QQ的即时通信程序(十一)
此为网络编程的一个系列,后续会把内容补上....
- [C# 网络编程系列]专题八:P2P编程
引言: 前面的介绍专题中有朋友向我留言说介绍下关于P2P相关的内容的,首先本人对于C#网络编程也不是什么大牛,因为能力的关系,也只能把自己的一些学习过程和自己的一些学习过程中的理解和大家分享下的,下面 ...
- [C# 网络编程系列]专题五:TCP编程
转自:http://www.cnblogs.com/zhili/archive/2012/08/25/2656840.html 前言 前面专题的例子都是基于应用层上的HTTP协议的介绍, 现在本专题来 ...
- [C# 网络编程系列]专题四:自定义Web浏览器
转自:http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html 前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发 ...
- [C# 网络编程系列]专题三:自定义Web服务器
转自:http://www.cnblogs.com/zhili/archive/2012/08/23/2652460.html 前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网 ...
- [C#网络编程系列]专题一:网络协议简介
转自:http://www.cnblogs.com/zhili/archive/2012/08/11/NetWorkProgramming.html 因为这段时间都在研究C#网络编程的一些知识, 所以 ...
随机推荐
- IOS中的NSTimer定时器详解
/* 在IOS中有多种定时器,这里我对NSTimer定时器做了一个简单的介绍.如果你是小白,你可能会从这篇文章中学习到一些知识,如果你是大牛,请别吝啬你的评论,指出我的不足,你的质疑是对我最大的帮助. ...
- ASP.NET跨页面传值技巧
1 使用QueryString变量 QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用 ...
- JS 浮点型数字运算(转)
示例: var num1=3.3; var num2=7.17; var ret=parseFloat(num1)+parseFloat(num2); //ret的值为:10.469999999999 ...
- IOS 学习日志 2015-3-13
前面几天在看C ,但是没有做笔记,现在在看Objective--C ,开始做笔记,希望每一天都有成长吧 Objective--C 关键字 1 @import 导入 注意<>||" ...
- 检查mysql数据库是否存在坏表脚本
#!/bin/bash #此脚本的主要用途是检测mysql服务器上所有的db或者单独db中的坏表 #变量说明 pass mysql账户口令 name mysql账号名称 data_path mysql ...
- tp_shop解读1
由于想弄一个商城,因此研究了一下tp_shop,这个据说能完成几乎所有的功能. 考虑到原有的例子过于复杂,因此把所有相关的数据都删除了,结果上来就出错了,查了两天,大致弄清楚了状况. 关于错误的原因 ...
- spring mvc 和mybatis整合 的异常处理
1.自定义异常信息类 通过构造函数来实现异常信息的接收 public class CustomException extends Exception { //异常信息 private String m ...
- Dataset
1,if(ds == null) 这是判断内存中的数据集是否为空,说明DATASET为空,行和列都不存在!! 2,if(ds.Tables[0].Count == 0) 这应该是在内存中存在一个DAT ...
- CentOS6.6源码编译升级GCC至4.8.2
升级前提 源码编译需要至少要有一个可用的gcc编译器. 可以用过yum自动安装或者手动下载rpm包安装. 通过yum可以看到至少需要下面这些安装包,所以可以到许多rpm package站点中搜索下载相 ...
- 【python】for循环一列
a="哈哈哈哈,笑死我了"for i in a: print (i, end=' ') 结果 哈 哈 哈 哈 , 笑 死 我 了