1、发送请求表示要向Clinet test发送文件,并发送文件大小和文件名
SEND:
<
iq
xmlns
="jabber:client"
id
="agsXMPP_6"
to
="Receive @localhost/"
type
="set"
><
si
xmlns
="http://jabber.org/protocol/si"
profile
="http://jabber.org/protocol/si/profile/file-transfer"
id
="b3b5f49c-8a94-49e2-908a-3de694b98af0"
><
file
xmlns
="http://jabber.org/protocol/si/profile/file-transfer"
name
="MiniClient.exe.config"
size
="382"
><
range
/></
file
><
feature
xmlns
="http://jabber.org/protocol/feature-neg"
><
x
xmlns
="jabber:x:data"
type
="form"
><
field
type
="list-single"
var
="stream-method"
><
option
><
value
>
http://jabber.org/protocol/byReceive reams
</
value
></
option
></
field
></
x
></
feature
></
si
></
iq
>
2、Receive 收到Send发实来的请求后,发送出响应流
RECV:
<
iq
xmlns
="jabber:client"
to
="Send@localhost"
type
="result"
id
="agsXMPP_6"
><
si
xmlns
="http://jabber.org/protocol/si"
id
="b3b5f49c-8a94-49e2-908a-3de694b98af0"
><
feature
xmlns
="http://jabber.org/protocol/feature-neg"
><
x
xmlns
="jabber:x:data"
type
="submit"
><
field
var
="stream-method"
><
value
>
http://jabber.org/protocol/byReceive reams
</
value
></
field
></
x
></
feature
></
si
></
iq
>
3、Send收到Receive 愿意接收的响应后,发出如下XML流
SEND:
<
iq
xmlns
="jabber:client"
id
="agsXMPP_7"
to
="Receive@localhost"
type
="set"
><
query
xmlns
="http://jabber.org/protocol/bySendreams"
sid
="71f1b875-4d84-429c-b39d-7dabcd400f3d"
><
streamhost
jid
="Send@localhost/MiniClient"
host
="localhost"
port
="1000"
/><
streamhost
jid
="proxy.ag-software.de"
host
="proxy.ag-software.de"
port
="7777"
/></
query
></
iq
>
注意这里注要是代理的设置,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;
// // Send(iq);
// iq.Type = IqType.set;
// this.Send(iq);
ProcessOobIQ(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;
// // Send(iq);
// iq.Type = IqType.set;
// this.Send(iq);
ProcessOobIQ(iq);
}
}
这里我们讲解完了服务器是如何处理用户互传文件,以后我将继续讲解客户端的实现原理.
这篇文章本来是昨晚上写好的,但由于源码留在公司了,所以今早上才贴出来。