MSNPSharp項目地址: sharp
源代碼svn地址:
我們直入正題MSNPSharp的消息發送機制的確和大部分人想的不太一樣一般人概念上發送消息就一個步驟調用自己寫的 SendXXXX 函數(該函數實現向某個用戶發送網絡數據)就可以直接實現向對方通信了其實這樣做要有個前提那就是你的SendXXX函數(下文簡稱Send)在被調用的時候要麼它能同步地(是的同步很重要)找到你要的目標用戶並且立即建立連接發送數據要麼它就把和對方握手緩沖向目標用戶建立連接成功之前輸入數據這些功能封裝了以至於調用者根本看不見這些步驟然而遺憾的是為了能讓程序員更靈活地控制發送消息的各個步驟MSNPSharp的SBMessageHandlerSendtextMessage函數設計不符合以上所有假設換言之你必須自己處理連接中的所有過程
很多人看到這裡可能會覺得這樣做實在太麻煩其實不然只要你了解了MSN向對方發送消息的整個過程就會覺得很簡單了
要使用MSNPSharp向你的好友發送消息首先必須建立一個Conversation對象這個對象可以通過調用Messenger類的CreateConversation函數獲得
建立了Conversation就可以通話了麼?答案是否定的因為這個Conversation這時候只有你一個人就好比你要向一個朋友通電話你直接拿起話筒就能和對方說話麼?
於是下一步我們該干什麼呢?讓我們回到通電話的那個例子上來我們拿起話筒理所當然做的第二件事情就是——撥號MSNPSharp也一樣你得撥號把對方邀請到你的Conversation裡面來這很簡單調用你先前得到的那個Conversation對象的Invite函數那個函數只有一個參數就是目標好友的Windows Live 帳號(前提是他沒有Block你)或者干脆就是你目標好友的Contact對象
完事了麼?很明顯沒有你撥號了之後還得等人接了才能通話當然在現實生活中完成這個動作很簡單你只需要拿著話筒等待就可以了因為撥號的這個過程是線性的(或者說是同步的)動作一個接一個地發生但是寫程序就沒有那麼走運了要知道Invite對方直到對方響應可能是一個很長的過程如果是同步的話那麼可能需要等待很長的時間以至於你不得不建立多條線程來處理每一個Invite所以MSNPSharp采用的是異步+事件通知的設計Invite後Invite函數立即返回當對方接聽後會在ConversationSwitchBrard觸發一個事件ContactJoined 這個時候你才可以用 ConversationSwitchBoardSendTextMessage向對方發送消息
通常很多人在ContactJoined事件之前就向對方調用SendTextMessage那結果只有一個發送失敗如果在ContactJoined事件之前UI又有幾條消息要被指定發送那麼建議先用個隊列或數組之類保存這些消息等ContactJoined事件觸發了之後再發送
事情看上去大功告成了但是不得不告訴各位一個壞消息提供通話服務的MSN電信局很吝啬如果你倆通話過程中超過秒到一分鐘一言不發它會把你們的通話掐斷(事實上應該是如果對方使用的是官方的MSN客戶端對方主動退出據測試)這個時候 ConversationSwitchBard 的 ContactLeft 事件會被觸發通知你對方用戶退出ConversationConversationSwitchBoardContactsCount屬性會自減表示在此Conversation裡面的Contact少了一個(如果一個Conversation裡面所有對方用戶都退出了會觸發AllContactsLeft事件這時可以直接調用ConversationSwitchboardClose()關閉Conversation)
這時問題就來了如果我想向一個因為長時間不發送消息而退出的用戶重新發送消息該怎麼辦呢?恩是的重新調用Messanger CreateConversation再建立一個Conversation Invite他們一次但是請記住就是在他們Left之前把退出的用戶記錄下來要不然你不知道該重新邀請誰還有千萬別忘記在ContactJoin之前把要發送的消息緩沖join之後才能發送
最後加一句所有的示例代碼都可以在MSNPSharp的那個Example客戶端看到
//本代碼取自
MSNPSharp Example Client ConversationFormcs
private void Switchboard_ContactJoined(object sender ContactEventArgs e)
{
if (conversationTextBoxInvokeRequired)
{
Delegate_Switchboard_ContactJoined d = new Delegate_Switchboard_ContactJoined(Switchboard_ContactJoined);
object[] args ={ };
args[] = sender;
args[] = e;
conversationTextBoxInvoke(d args); //線程切換
}
else
{
conversationTextBoxText += * + eContactName + joined the conversation\r\n;
_contactStatus[eContactMailToLowerInvariant()] = true;
//Send all messages and nudges
if (_messagequeneCount > )
{
for (int i = ; i < _messagequeneCount; i++)
{
_conversationSwitchboardSendTextMessage(_messagequene[i]); //把之前緩沖的消息發送出去
}
_messagequeneClear();
}
if (_nudgequeneCount > )
{
foreach (object ob in _nudgequene)
{
_conversationSwitchboardSendNudge(); //把之前緩沖的閃屏發送出去
}
_nudgequeneClear();
}
}
}
private void Switchboard_ContactLeft(object sender ContactEventArgs e)
{
if (conversationTextBoxInvokeRequired)
{
conversationTextBoxInvoke(new ContactChangedEventHandler(Switchboard_ContactLeft)
new object[] { sender e });
}
else
{
conversationTextBoxText += * + eContactName + left the conversation\r\n;
if (!_leftusersContains(eContactMail))
_leftusersAdd(eContactMail); //記錄下離開的用戶
_contactStatus[eContactMailToLowerInvariant()] = false;
}
}
void Switchboard_AllContactsLeft(object sender EventArgs e)
{
RemoveEvent();
ConversationSwitchboardClose(); //所有的用戶都離開了關閉Conversation
}
//發送消息
private void SendInput()
{
// check whether there is input
if(inputTextBoxTextLength == ) return; //不能發送空消息
TextMessage message = new TextMessage(inputTextBoxText);
_typingMessageSended = false;
inputTextBoxText = StringEmpty;
conversationTextBoxText += You say: + messageText + \r\n;
//All contacts left recreate the conversation
if (ReInvite()) //如果對方已經退出會話重新邀請
{
_messagequeneAdd(message); //緩沖消息暫不發送
return;
}
ConversationSwitchboardSendTextMessage(message); //發送消息
}
//重新邀請
private bool ReInvite()
{
if (!ConversationSwitchboardIsSessionEstablished) //如果發現Session已經斷開(Conversation已經關閉)
{
_clientformDicconversationRemove(_conversation);
RemoveEvent();
_conversation = _conversationMessengerCreateConversation(); //重新簡歷Conversation
_clientformDicconversationAdd(_conversation this);
AddEvent();
foreach (string account in _leftusers)
{
_conversationInvite(account); //邀請退出了的用戶
}
_leftusersClear();
return true;
}
return false;
}
From:http://tw.wingwit.com/Article/program/ASP/201311/21827.html