XMPP协议即时通讯工具实现原理.docx
- 文档编号:11881041
- 上传时间:2023-04-08
- 格式:DOCX
- 页数:10
- 大小:175.23KB
XMPP协议即时通讯工具实现原理.docx
《XMPP协议即时通讯工具实现原理.docx》由会员分享,可在线阅读,更多相关《XMPP协议即时通讯工具实现原理.docx(10页珍藏版)》请在冰豆网上搜索。
XMPP协议即时通讯工具实现原理
XMPP协议--即时通讯工具实现原理(服务器,客户端)
分类:
C#jabber/XMPP2010-12-1021:
26292人阅读评论(0)收藏举报
第一篇:
.net平台 基于 XMPP协议的即时消息服务端简单实现
昨天抽空学习了一下XMPP,在网上找了好久,中文的资料太少了所以做这个简单的例子,今天才完成。
公司也正在准备开发基于XMPP协议的即时通讯工具所以也算是打一个基础吧!
如果你还没有了解过XMPP请先阅读附录中链接的文章,本实例是基agsXMPP上开发的,agsXMPP是C#写的支持开源XMPP协议软件,我们可以在agsXMPP上快速构建自已的即时通讯平台,我的这个例子只是修改了服务器端,因为agsXMPP本身自带的服务器端没有实现聊天功能、签名和登录密码认证。
服务器端XmppSeverConnection类事件
//在流开始时触发,一般是最初的响应流
streamParser.OnStreamStart += new StreamHandler(streamParser_OnStreamStart);
//在流结束时触发,一般是发送
stream>并关闭套接字连接streamParser.OnStreamEnd += new StreamHandler(streamParser_OnStreamEnd);
//在接收到流结点时触发,这是用得最多的,常用的
streamParser.OnStreamElement += new StreamHandler(streamParser_OnStreamElement);
//此处处理大部份的消息,包括消息路由
private void streamParser_OnStreamElement(object sender, Node e)
{
Console.WriteLine("OnStreamElement:
" + e.ToString());
if (e.GetType() == typeof(Presence))
{
// 路由presences节
}
else if (e.GetType() == typeof(Message))
{
// 路由messages节
}
else if (e.GetType() == typeof(IQ))
{
//处理IQ节
}
}
///
/// IQ节处理函数
///
/// .
private void ProcessIQ(IQ iq)
{
if (iq.Query.GetType() == typeof(Auth))
{
Auth auth = iq.Query as Auth;
this.Username = auth.Username.ToString();
switch (iq.Type)
{
case IqType.get:
iq.SwitchDirection();
iq.Type = IqType.result;
auth.AddChild(new Element("password"));
auth.AddChild(new Element("digest"));
Send(iq);
break;
case IqType.set:
// 进行登录认证
if (AccountBus.CheckLogin(auth.Username, auth.Digest, this.SessionId))
{
iq.SwitchDirection();
iq.Type = IqType.result;
iq.Query = null;
Send(iq);
Console.WriteLine(auth.Username + "登录了" + " 登录时间:
" + System.DateTime.Now.ToString());
}
else
{
//登录失败返回错误信息
iq.SwitchDirection();
iq.Type = IqType.error;
iq.Query = null;
Send(iq);
}
break;
}
}
else if (iq.Query.GetType() == typeof(Roster))
{
ProcessRosterIQ(iq);
}
}
///
/// 处理IQ节的杂项数据.
///
/// The iq.
private void ProcessRosterIQ(IQ iq)
{
if (iq.Type == IqType.get)
{
// 发送IQ节的杂项数据
//这里我用来下载好友列表
iq.SwitchDirection();
iq.Type = IqType.result;
List
friendList = AccountBus.GetFriendName(this.username);
foreach (string str in friendList)
{
RosterItem ri = new RosterItem();
ri.Name = str.Trim();
ri.Subscription = SubscriptionType.both;
ri.Jid = new agsXMPP.Jid(str.Trim() + "@localhost");
ri.AddGroup("localhost");
iq.Query.AddChild(ri);
}
Send(iq);
}
}
服务器端开启监听5222端口
while (running)
{
////
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("等待连接...");
listener.BeginAccept(new AsyncCallback(AcceptCallback), null);
//// 等待客户端连接
allDone.WaitOne();
}
如果收到客户端请求就异步调用AcceptCallback初始化套接字连接
并为客户端建立一个通信线程,新建初始化套接字连接采用异步调
用读取套接字信息
public XmppSeverConnection(Socket sock)
:
this()
{
m_Sock = sock;
m_Sock.BeginReceive(buffer, 0, BUFFERSIZE, 0, new AsyncCallback(ReadCallback), null);
m_Sock.SendTimeout = 100;
}
客户端与服务器端的交互过程
1客户端异步向服务器端发送连接请求
streamto='localhost'xmlns='jabber: client'xmlns: stream='http: //etherx.jabber.org/streams'version='1.0'xml: lang='en'> 2服务器端收到请求,初始化回应流,并随机生成一相SessionID streamxmlns: stream="http: //etherx.jabber.org/streams"from="localhost"id="30e3b8c0"> 3等待服务器返回消息后客户端发送用户名(由于在客户端采用了异步调用 方式,所以UI界面感觉不到等待) client"id="agsXMPP_1"type="get"to="localhost"> iq: auth"> 4服务器端收到用户名等待用户提供密码 client"from="localhost"type="result"id="agsXMPP_1"> iq: auth"> 5客户端提供加密后的密码 client"id="agsXMPP_2"to="localhost"type="set"> iq: auth"> 6服务器端从数据库验证用户名和密码,并返回结果 iqxmlns="jabber: client"from="localhost"type="result"id="agsXMPP_2"/> 7如果返回错误,客户端提示并终断连接,否则客户端发送响应数据 8 服务器端返回数据 9 客户端发送状态, 10服务器收到状态,发送IQ节并通知其它用户. 项目解决方案和类图 附录: 推荐使用Pandion作为客户端 服务器端下载 客户端下载 agsXMPP 源码下载 XMPPRFC3920 可扩展消息出席协议 jabber官方网站 第二篇: 基于 XMPP协议的服务器端 文件互传的简单实现 昨天我们讲了客户端实现用户互发消息的原理,今天我们继续学习一下基于XMPP协议的文件传输,首先我们假设用户已经登录,这里我们假设ClinetSend对ClinetReceive 发送文件,这里记录了ClinetSend的发送和接收XML流记录 1、发送请求表示要向Clinettest发送文件,并发送文件大小和文件名 SEND: client" id="agsXMPP_6" to="Receive @localhost/" type="set"> //jabber.org/protocol/si" profile="http: //jabber.org/protocol/si/profile/file-transfer" id="b3b5f49c-8a94-49e2-908a-3de694b98af0"> //jabber.org/protocol/si/profile/file-transfer" name="MiniClient.exe.config" size="382"> //jabber.org/protocol/feature-neg"> x: data" type="form"> //jabber.org/protocol/byReceive reams 2、Receive 收到Send发实来的请求后,发送出响应流 RECV: client" to="Send@localhost" type="result" id="agsXMPP_6"> //jabber.org/protocol/si" id="b3b5f49c-8a94-49e2-908a-3de694b98af0"> //jabber.org/protocol/feature-neg"> x: data" type="submit"> //jabber.org/protocol/byReceive reams 3、Send收到Receive 愿意接收的响应后,发出如下XML流 SEND: client" id="agsXMPP_7" to="Receive@localhost" type="set"> //jabber.org/protocol/bySendreams" sid="71f1b875-4d84-429c-b39d-7dabcd400f3d"> 注意这里注要是代理的设置,agsXMPP 自带的客户端是使用代理传输数据的,所以必须对其做相应的修改,使其支持局域网内支持发送文件. 下面我们来看一下服务器端是如何路由消息的呢? 从上面所发送的XML流我们可以看出,实际上用户传送文件所发送的都是IQ节,我们必须对IQ节进行路由才能使其找到相应的接收者 ,所以我们需要在XmppServerConnection类中添加如下代码: private void ProcessIQ(IQ iq) { //传送文件得理 if (iq.Query == null) { if(iq.Type == IqType.result) this.Send(iq); ProcessOobIQ(iq); }else if (iq.Query.GetType() == typeof(Auth)) { Auth auth = iq.Query as Auth; this.Username = auth.Username.ToString(); switch (iq.Type) { case IqType.get: iq.SwitchDirection(); iq.Type = IqType.result; auth.AddChild(new Element("password")); auth.AddChild(new Element("digest")); Send(iq); break; case IqType.set: // Here we should verify the authentication credentials if (AccountBus.CheckLogin(auth.Username, auth.Digest, this.SessionId)) { iq.SwitchDirection(); iq.Type = IqType.result; iq.Query = null; Send(iq); Console.WriteLine(auth.Username + "登录了" + " 登录时间: " + System.DateTime.Now.ToString()); } else { // iq.SwitchDirection(); iq.Type = IqType.error; iq.Query = null; Send(iq); } break; } } else if (iq.Query.GetType() == typeof(Roster)) { ProcessRosterIQ(iq); }//用代理传送文件处理 else if(iq.Query.FirstChild ! =null) { // iq.SwitchDirection(); // //iq.Type = IqType.result; // //
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- XMPP 协议 即时通讯 工具 实现 原理