您的位置:首页 > 其它

当机器人遇到咱们, 就要聊聊天. Message! DotMSN2.0 Robot(三) [原鸟]

2007-08-14 09:42 344 查看
内容记:

MSN Robot就是MSN机器人, 也可以喊成MSN聊天机器人.再解释就是会自动和你聊天的MSN,再再解释就是……啊, 我短路了(耳朵冒烟中)

本随笔是MSN Robot随笔系列第三篇, 内容是关于MSN Robot信息发送和接收.

我是下边讲解的例子
//消息发送

public void SendInput(string strMessage)

{

string inputTextBox = strMessage;

// 判断是否超时

// 这里是非常关键的地方, 可以看下边的解释

if (!GetTimeOverTimeSpan())

{

from.richTextBox3.AppendText(STR_CFG_OVERTIME);

return;

}

//消息为空

if (inputTextBox.Length == 0)

{

from.richTextBox3.AppendText(STR_CFG_MESSAGEEMPTY);

return;

}

//SwitchboardProcessor为null

if (Conversation.SwitchboardProcessor == null)

{

from.richTextBox1.AppendText(STR_CFG_SBPROCESSOR_NULL);

return;

}

// if there is no switchboard available, request a new switchboard session

if (Conversation.SwitchboardProcessor.Connected == false)

{

Conversation.Messenger.Nameserver.RequestSwitchboard(Conversation.Switchboard, this);

}

// Contacts为, 用户已经left会话

if (Conversation.Switchboard.Contacts.Count == 0)

{

from.richTextBox1.AppendText(STR_CFG_CONTACT_LEFT);

return;

}

// 准备消息

TextMessage message = new TextMessage(inputTextBox);

/* You can optionally change the message's font, charset, color here.

* For example:

* message.Color = Color.Red;

* message.Decorations = TextDecorations.Bold;

*/

// 终于可以发送了

Conversation.Switchboard.SendTextMessage(message);

}

也许咱们已经对照着DotMSN来试着实现消息的接收和发送了, 又也许你会遇到这样一个问题, 就是发送消息和接收消息会出现失败的情况, 或者是发送出去的消息对方没有收到, 又或者是对方发来的消息自己没有收到. 有的时候这种情况会很明显, 有的时候又靠着rp问题才能重现. 再也许你会奇怪另一个问题, 就是很哲理的.. 这个消息是怎么发出去的? Ok, 它们是一个答案, 关于后一个问题咱们先来解决它的表象吧 J 好吗?

在DotMSN里, 消息发送是分为这样几步的.

一, 取到用户Contact

比如:

Contact selectedContact = (Contact)ContactListView.SelectedItems[0].Tag;

二, 创建Conversation, 也可以叫创建会话.

比如:

Conversation Cconversation = messenger.CreateConversation();

三, 将用户加入到会话中

Conversation.Invite(selectedContact);

四, 发送消息

Conversation.Switchboard.SendTextMessage(message);

看 J 是不是很简单? 行云流水丝绸一样飘过. 消息就这样发送出去了.

等等! 是不是发送成功了呢? 在这样天鹅绒光滑的水面下有没有什么杀人的石头呢?

嗯, 应该是有, 不然科幻小说的作者就没有写下去的动力了.

比如, 最不幸的就是本人, 某一天月黑风高在早晨可以像小舟一样划过水面的程序, 下午就触礁了.

在消息发送时

if (Conversation.SwitchboardProcessor.Connected == false)

这句上出现了永远过不去的, 对象没有绑定到实例. 这时候SwitchboardProcessor为null

为什么会这样子?! 为什么会出现永恒的, 突然的, null的地狱呢? 这是诅咒还是宿命?!

路人甲: 这是rp问题….

Ok, 本人是不能允许我这样风华绝代大帅哥出现rp问题的. 抄刀灭之!

这时候突然想到曾经神仙老爷爷说过的话, 发送消息之前一定要双方进入会话.

顺藤摸瓜赶紧查, yi, 为什么在Invite好友之后程序没有马上触发Switchboard_ContactJoined事件通知咱们用户进入对话呢?

是不是在Invite之后要等待服务器的通知? 嗯, 一定是这样.

再敬仰的去看DotMSN的程序… yi, 为什么在Invite好友之后打了一个很二的时间差呢? 如果Invite的时候有网络延迟, 运行到send的时候对方还没有加入会话呢?! o, null hell, send fail.

于是在咱们的相关消息函数中有这样一段代码:

// 判断是否超时

// 这里是非常关键的地方, 可以看下边的解释

if (!GetTimeOverTimeSpan())

{

from.richTextBox3.AppendText(STR_CFG_OVERTIME);

return;

}

可以看一看它的函数本体, 哗, 是一个很白痴的while循环! 它在一直等待一个名字叫bRun的白痴看不懂是什么的标记变成true

// 判断是否超时

private bool GetTimeOverTimeSpan()

{

DateTime tBeginTime = DateTime.Now;

DateTime tCurrTime;

//等待ContactJoined事件先行触发, Contact进入Conversation后才能继续处理.

while (!bRun)

{

tCurrTime = DateTime.Now;

TimeSpan dif = tCurrTime - tBeginTime;

// 计算超时, 如果秒后Contact尚未进入, 就断定超时退出处理.

if (dif.Seconds > 10)

{

//from.richTextBox3.AppendText(STR_CFG_OVERTIME);

return false;

}

}

return true;

}

你会指着我的鼻子喊: 这个叫bRun的白痴标记在什么时候才能变成true呢?!

答案是 在好友已经加入对话的事件里.

private void Switchboard_ContactJoined(object sender, ContactEventArgs e)

{

bRun = true;

}

嗯, 结论是, 世界终于和平, 人类终于美好了~~ 王子和公主幸福的生活在一起, 相知相伴, 永不分离.

流氓: 等等! 还没结束, 在程序的后台又发生了什么呢??!!

可怜的俺: 大佬.. 饶了我吧.. 今天打了一下午字( 大于等于1 ), 手都麻了~~~ 而且, 而且这个时候我是下班的可怜人呐 L 55555….

转上几个字, 希望接着了解后台可以顺着读一下, 门清~

在MSN里的即时通讯是基于session的。想进行对话的两个人必须在session模式当中。除非我们同其他用户开始一个聊天session,否则我们是不能发送/接受信息的。
基本上有两种途径可以使一个用户处于一个聊天session中
.1 用户向另一个用户发送一个聊天session请求
2 用户接收从另一个用户那里发送来的聊天session请求
接下来将分别详细介绍这两种途径

用户向另一个用户发送一个聊天session请求
客户端(用户)向服务器发送一个命令,以获取接线总机(SwitchBoard)服务器的地址.所有的即时通讯交谈都必须通过接线总机服务器实现。

XFR9 SB
此接线总机服务器返回此服务器的ip地址,连接端口,和一个CKI杂列。CKI 是一个安全包,用户必须使用此CKI杂列连接上接线总机服务器。

XFR9 SB 64.4.13.88:1863 CKI1989487642.2070896604
现在这次我们将向接线总机服务器进行一次新的连接。而且我们上次对MSN即时通服务器的连接必须要保持,否则我们将会登出。

在我们连接上接线总机服务器之后,我们将向此接线总机服务器发送以下命令:
USR 1 venky_dude@hotmail.com 989487642.2070896604
如果我们发送的这个CKI杂列正确的话,接线服务器将会返回
USR 1 OK venky_dude@hotmail.com venkat
当以上做完之后,接下来这个用户要做的就是要把另一个用户”叫到”此聊天session中了,这可以通过发送下面的命令完成
CAL 2 deadxxx@hotmail.com
服务器将会向此用户回应一个session号,同时也会将此session号发送给另一个用户。
如果另一个用户准备好聊天,并向做出回应时,服务器将向我们发送如下命令

JOI deadlee@hotmail.com Venkatesh
这条命令表示另一个用户加入了聊天当中,我们现在可以接受和发送信息了

看, 一直到这里, 咱们的Invite终于执行到ContactJoined了!

用户接收从另一个用户那里发送来的聊天session请求
当我们被一个用户邀请到一个聊天session中时,认证服务器将向我们发送如下的信息.
RNG 11742066 64.4.13.74:1863 CKI 989495494.750408580 deaxxxx@hotmail.com Venkatesh
上面的命令包含了session号,接线服务器的ip地址,端口,CKI杂列及向我们发出交谈请求的用户信息。
现在我们将向接线服务器进行一次新的连接。同样我们上次对MSN即时通服务器的连接必须要保持,否则我们将会登出。

我们连接上接线服务器,并且发送如下命令

ANS 1 venky_dude@hotmail.com 989495494.750408580 11742066
上面的命令包含了我们的登陆名,我们接收到的CKI杂列和session号.
服务器将回应如下信息
IRO 1 1 1 deaxxxx@hotmail.com Venkatesh 和 ANS 1 OK
我们现在就可以发送和接收信息了。

在我们发送和接收信息之前,让我们了解一下信息是如何创建的
我们发送信息时,将首先建立一个头信息如下所示
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
X-MMS-IM-Format: FN=Microsoft%20Sans%20Serif; EF=; CO=0; CS=0; PF=22

然后使用如下的方式发送
MSG2 N137 MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
X-MMS-IM-Format: FN=Microsoft%20Sans%20Serif; EF=; CO=0; CS=0; PF=22

hello
其中2是测试号,我们每发送一次信息,此号就会随着增加。137是指我们发送信息的长度。在上面的例子中就是头信息和我们发送的信息”hello”的长度。

我们发送的信息和上面的例子是差不多的。

下面是我们接受到的一个信息的例子
MSG deaxxxx@hotmail.com Venkatesh 137
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
X-MMS-IM-Format: FN=Microsoft%20Sans%20Serif; EF=; CO=0; CS=0; PF=22

hello

当另一用户正在输入信息时,我们会收到如下信息
MSG deaxxxx@hotmail.com Venkatesh 100
MIME-Version: 1.0
Content-Type: text/x-msmsgscontrol
TypingUser: deaxxxx@hotmail.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: