`
maxwellens
  • 浏览: 12787 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

MSNPSharp发送消息过程详解

阅读更多
    我们直入正题。MSNPSharp的消息发送机制的确和大部分人想的不太一样,一般人概念上发送消息就一个步骤:调用自己写的 SendXXXX 函数(该函数实现向某个用户发送网络数据)就可以直接实现向对方通信了。其实这样做要有个前提,那就是你的SendXXX函数(下文简称Send)在被调用的时候,要么它能同步地(是的,同步很重要)找到你要的目标用户,并且立即建立连接发送数据,要么它就把和对方握手、缓冲向目标用户建立连接成功之前输入数据这些功能封装了,以至于调用者根本看不见这些步骤。然而,遗憾的是,为了能让程序员更灵活地控制发送消息的各个步骤,MSNPSharp的SBMessageHandler.SendtextMessage函数设计不符合以上所有假设。换言之,你必须自己处理连接中的所有过程。

    很多人看到这里可能会觉得这样做实在太麻烦,其实不然,只要你了解了MSN向对方发送消息的整个过程就会觉得很简单了。

    要使用MSNPSharp向你的好友发送消息,首先必须建立一个Conversation对象,这个对象可以通过调用Messenger类的CreateConversation函数获得。

    建立了Conversation就可以通话了么?答案是否定的,因为这个Conversation这时候只有你一个人,就好比你要向一个朋友通电话,你直接拿起话筒就能和对方说话么?

    于是下一步我们该干什么呢?让我们回到通电话的那个例子上来。我们拿起话筒,理所当然做的第二件事情就是——拨号。MSNPSharp也一样,你得“拨号”把对方邀请到你的Conversation里面来,这很简单,调用你先前得到的那个Conversation对象的Invite函数,那个函数只有一个参数,就是目标好友的Windows Live 帐号(前提是他没有Block你),或者干脆就是你目标好友的Contact对象。

    完事了么?很明显没有。你拨号了之后还得等人接了才能通话。当然在现实生活中完成这个动作很简单:你只需要拿着话筒等待就可以了,因为拨号的这个过程是线性的(或者说是同步的),动作一个接一个地发生。但是写程序就没有那么走运了,要知道Invite对方直到对方响应可能是一个很长的过程,如果是同步的话,那么可能需要等待很长的时间,以至于你不得不建立多条线程来处理每一个Invite。所以MSNPSharp采用的是异步+事件通知的设计:Invite后Invite函数立即返回,当对方“接听”后,会在Conversation.SwitchBrard触发一个事件:ContactJoined ,这个时候你才可以用 Conversation.SwitchBoard.SendTextMessage向对方发送消息。

    通常很多人在ContactJoined事件之前就向对方调用SendTextMessage,那结果只有一个:发送失败。如果在ContactJoined事件之前UI又有几条消息要被指定发送,那么建议先用个队列或数组之类保存这些消息,等ContactJoined事件触发了之后再发送。

    事情看上去大功告成了。但是不得不告诉各位一个坏消息,提供通话服务的MSN“电信局”很吝啬,如果你俩通话过程中超过30秒到一分钟一言不发,它会把你们的通话掐断(事实上应该是如果对方使用的是官方的MSN客户端,对方主动退出,据测试)。这个时候 Conversation.SwitchBard 的 ContactLeft 事件会被触发,通知你对方用户退出Conversation,Conversation.SwitchBoard.Contacts.Count属性会自减1,表示在此Conversation里面的Contact少了一个。(如果一个Conversation里面所有对方用户都退出了,会触发AllContactsLeft事件,这时可以直接调用Conversation.Switchboard.Close()关闭Conversation)

    这时问题就来了,如果我想向一个因为长时间不发送消息而退出的用户重新发送消息该怎么办呢?恩,是的,重新调用Messanger. CreateConversation再建立一个Conversation Invite他们一次。但是请记住就是,在他们Left之前把退出的用户记录下来,要不然你不知道该重新邀请谁,还有,千万别忘记,在ContactJoin之前把要发送的消息缓冲,join之后才能发送。

    最后加一句,所有的示例代码都可以在MSNPSharp的那个Example客户端看到。

//view plaincopy to clipboardprint?
//本代码取自MSNPSharp Example Client ConversationForm.cs    
  
       private void Switchboard_ContactJoined(object sender, ContactEventArgs e)   
        {   
            if (conversationTextBox.InvokeRequired)   
            {   
                Delegate_Switchboard_ContactJoined d = new Delegate_Switchboard_ContactJoined(Switchboard_ContactJoined);   
                object[] args ={ 0, 0 };   
                args[0] = sender;   
                args[1] = e;   
                conversationTextBox.Invoke(d, args);   //线程切换   
            }   
            else  
            {   
                conversationTextBox.Text += "* " + e.Contact.Name + " joined the conversation\r\n";   
                _contactStatus[e.Contact.Mail.ToLowerInvariant()] = true;   
  
                //Send all messages and nudges   
                if (_messagequene.Count > 0)   
                {   
                    for (int i = 0; i < _messagequene.Count; i++)   
                    {   
                        _conversation.Switchboard.SendTextMessage(_messagequene[i]); //把之前缓冲的消息发送出去   
                    }   
                    _messagequene.Clear();   
                }   
  
                if (_nudgequene.Count > 0)   
                {   
                    foreach (object ob in _nudgequene)   
                    {   
                        _conversation.Switchboard.SendNudge();  //把之前缓冲的闪屏发送出去   
                    }   
                    _nudgequene.Clear();   
                }   
            }   
        }   
  
        private void Switchboard_ContactLeft(object sender, ContactEventArgs e)   
        {   
            if (conversationTextBox.InvokeRequired)   
            {   
                conversationTextBox.Invoke(new ContactChangedEventHandler(Switchboard_ContactLeft),   
                    new object[] { sender, e });   
            }   
            else  
            {   
                conversationTextBox.Text += "* " + e.Contact.Name + " left the conversation\r\n";   
                if (!_leftusers.Contains(e.Contact.Mail))   
                    _leftusers.Add(e.Contact.Mail);          //记录下离开的用户   
                _contactStatus[e.Contact.Mail.ToLowerInvariant()] = false;   
            }   
        }   
  
        void Switchboard_AllContactsLeft(object sender, EventArgs e)   
        {   
            RemoveEvent();   
            Conversation.Switchboard.Close();  //所有的用户都离开了,关闭Conversation.   
        }  

//本代码取自MSNPSharp Example Client ConversationForm.cs 

       private void Switchboard_ContactJoined(object sender, ContactEventArgs e)
        {
            if (conversationTextBox.InvokeRequired)
            {
                Delegate_Switchboard_ContactJoined d = new Delegate_Switchboard_ContactJoined(Switchboard_ContactJoined);
                object[] args ={ 0, 0 };
                args[0] = sender;
                args[1] = e;
                conversationTextBox.Invoke(d, args);   //线程切换
            }
            else
            {
                conversationTextBox.Text += "* " + e.Contact.Name + " joined the conversation\r\n";
                _contactStatus[e.Contact.Mail.ToLowerInvariant()] = true;

                //Send all messages and nudges
                if (_messagequene.Count > 0)
                {
                    for (int i = 0; i < _messagequene.Count; i++)
                    {
                        _conversation.Switchboard.SendTextMessage(_messagequene[i]); //把之前缓冲的消息发送出去
                    }
                    _messagequene.Clear();
                }

                if (_nudgequene.Count > 0)
                {
                    foreach (object ob in _nudgequene)
                    {
                        _conversation.Switchboard.SendNudge();  //把之前缓冲的闪屏发送出去
                    }
                    _nudgequene.Clear();
                }
            }
        }

        private void Switchboard_ContactLeft(object sender, ContactEventArgs e)
        {
            if (conversationTextBox.InvokeRequired)
            {
                conversationTextBox.Invoke(new ContactChangedEventHandler(Switchboard_ContactLeft),
                    new object[] { sender, e });
            }
            else
            {
                conversationTextBox.Text += "* " + e.Contact.Name + " left the conversation\r\n";
                if (!_leftusers.Contains(e.Contact.Mail))
                    _leftusers.Add(e.Contact.Mail);          //记录下离开的用户
                _contactStatus[e.Contact.Mail.ToLowerInvariant()] = false;
            }
        }

        void Switchboard_AllContactsLeft(object sender, EventArgs e)
        {
            RemoveEvent();
            Conversation.Switchboard.Close();  //所有的用户都离开了,关闭Conversation.
        }view plaincopy to clipboardprint?
//发送消息   
private void SendInput()   
{   
  // check whether there is input   
  if(inputTextBox.Text.Length == 0) return;  //不能发送空消息   
  
   TextMessage message = new TextMessage(inputTextBox.Text);   
   _typingMessageSended = false;   
   inputTextBox.Text = String.Empty;   
   conversationTextBox.Text += "You say: " + message.Text + "\r\n";   
  
   //All contacts left, recreate the conversation   
   if (ReInvite())  //如果对方已经退出会话,重新邀请   
   {   
       _messagequene.Add(message);  //缓冲消息,暂不发送   
       return;   
   }   
 Conversation.Switchboard.SendTextMessage(message);  //发送消息   
  
}  

         //发送消息
         private void SendInput()
         {
           // check whether there is input
           if(inputTextBox.Text.Length == 0) return;  //不能发送空消息

            TextMessage message = new TextMessage(inputTextBox.Text);
            _typingMessageSended = false;
            inputTextBox.Text = String.Empty;
            conversationTextBox.Text += "You say: " + message.Text + "\r\n";

            //All contacts left, recreate the conversation
            if (ReInvite())  //如果对方已经退出会话,重新邀请
            {
                _messagequene.Add(message);  //缓冲消息,暂不发送
                return;
            }
          Conversation.Switchboard.SendTextMessage(message);  //发送消息

         }view plaincopy to clipboardprint?
//重新邀请   
private bool ReInvite()   
{   
    if (!Conversation.Switchboard.IsSessionEstablished)  //如果发现Session已经断开(Conversation已经关闭)   
    {   
        _clientform.Dicconversation.Remove(_conversation);   
        RemoveEvent();   
        _conversation = _conversation.Messenger.CreateConversation();  //重新简历Conversation   
        _clientform.Dicconversation.Add(_conversation, this);   
        AddEvent();   
        foreach (string account in _leftusers)   
        {   
            _conversation.Invite(account);  //邀请退出了的用户   
        }   
        _leftusers.Clear();   
        return true;   
    }   
    return false;   
}  

本文来自CSDN博客:http://blog.csdn.net/VirtualDesktop/archive/2008/06/09/2527465.aspx
分享到:
评论

相关推荐

    MSNPSHARP源码

    MSNPSharp_301_release.zip

    开源MSNPSharp源码(C#)

    开源MSNPSharp源码(C#)

    msnpsharp.dll,MSN好友列表获取权限拒绝解决办法

    MSN好友列表获取,在网上有开源版本的msnpsharp.dll,结果很多人拿来用,这个程序个问题就是在发布后,获取文件路径,并且生成一个资源文件,这里有权限拒绝的问题,经过精心调试程序,最终发现问题在哪里,并给出...

    MSNP-Sharp

    MSNP-Sharp是一个能与MSN Messenger(现Windows Live Messenger)服务连接并向...MSNPSharp支持MSN绝大部分的功能,包括:聊天,发送、接收离线消息,接收用户显示图片,更改自己显示图片,文件传送,闪屏震动等等。

    MSN通讯类库

    MSNP-Sharp是一个能与MSN Messenger(现Windows Live Messenger)服务连接并向...MSNPSharp支持MSN绝大部分的功能,包括:聊天,发送、接收离线消息,接收用户显示图片,更改自己显示图片,文件传送,闪屏震动等等。

    MSNPSharp_314_release

    MSNP-Sharp是一个能与MSN Messenger(现Windows Live Messenger)服务连接并向客户端编程人员提供相应的IM服务的“中间件”,其前身为DotMSN。它面向.NET开发人员,能使开发人员开发各种基于 Windows Live Messenger...

    MSNPSharp_40_RC2.zip

    MSNP-Sharp是一个能与MSN Messenger(现Windows Live Messenger)服务连接并向客户端编程人员提供相应的IM服务的“中间件”,其前身为DotMSN。它面向.NET开发人员,能使开发人员开发各种基于 Windows Live Messenger...

    MSN协议开发源代码(C#)

    MSNP-Sharp是一个能与MSN Messenger(现Windows Live Messenger)服务连接并向...MSNPSharp支持MSN绝大部分的功能,包括:聊天,发送、接收离线消息,接收用户显示图片,更改自己显示图片,文件传送,闪屏震动等等。

    MSNPSharp_401_release.zip_ICQ/即时通讯_C/C++_

    IM(C#)源码,可链接MSN

    .net 取得msn好友(需要提供用户密码)

    msnpsharp 博文链接:https://ljl-xyf.iteye.com/blog/758235

    MSNSharp with Video Conference-开源

    在MSN World中,用户不会彼此直接通信。我们研究了P2P开源视频/音频会议系统。 经过研究,我发现VideoNet应用程序适合并修改了VideoNet,并适应了MSNPSharp。 我使用了模拟编解码器。

Global site tag (gtag.js) - Google Analytics