<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_TianFang</title><subtitle type="text">相濡以沫，不如相忘于江湖</subtitle><id>http://feed.cnblogs.com/blog/u/15688/rss</id><updated>2012-05-12T07:32:39Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/15688/rss"/><entry><id>http://www.cnblogs.com/TianFang/archive/2012/05/06/2485986.html</id><title type="text">用C#实现MSN客户端（五）</title><summary type="text">在前文中介绍过，MSN协议中服务器分为NS（NotificationServer）和SB（Switchboard）等几种，其中NS主要用来传输控制命令，而SB则用来传输会话，每个会话对应着一个SB。在一个MSN客户端中，是连接着一个NS和多个SB的。创建会话这里以两个客户端ClientA和ClientB和交谈为例，假定ClientA创建一个会话，并邀请ClientB参加会话，则它们之间的交互过程如下：1. ClientA发送XFR命令创建SessionBoard，服务器返回SessionBoard地址&gt;&gt;&gt; XFR 15 SB\r\n&lt;&lt;&lt; XFR 15 </summary><published>2012-05-06T07:32:00Z</published><updated>2012-05-06T07:32:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/05/06/2485986.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/05/06/2485986.html"/><content type="html">&lt;p&gt;在前文中介绍过，MSN协议中服务器分为NS（NotificationServer）和SB（Switchboard）等几种，其中NS主要用来传输控制命令，而SB则用来传输会话，每个会话对应着一个SB。在一个MSN客户端中，是连接着一个NS和多个SB的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;创建会话&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这里以两个客户端ClientA和ClientB和交谈为例，假定ClientA创建一个会话，并邀请ClientB参加会话，则它们之间的交互过程如下：&lt;/p&gt;&lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/TianFang/201205/201205061531416905.png" /&gt;&lt;/p&gt;&lt;p&gt;1.  ClientA发送XFR命令创建SessionBoard，服务器返回SessionBoard地址&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;gt;&amp;gt;&amp;gt; XFR 15 SB&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0); font-family: Consolas; font-size: 9pt;"&gt;&amp;lt;&amp;lt;&amp;lt; XFR 15 SB &lt;span style="background-color: rgb(217, 217, 217);"&gt;207.46.108.37:1863&lt;/span&gt; CKI &lt;span style="background-color: rgb(217, 217, 217);"&gt;17262740.1050826919.32308&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;服务器的XFR应答消息中包含三个参数，第一个参数为SB服务器的地址，第二个参数为认证类型，固定为CKI，第三个参数为后面服务器的认证Key值，后面会用到。&lt;/p&gt;&lt;p&gt;2. ClientA连接SessionBoard，并发送USR命令进行身份认证。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;lt;o&amp;gt; Client Connects to 207.46.108.37 1863 (Switchboard)&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;gt;&amp;gt;&amp;gt; USR 1 &lt;span style="background-color: rgb(217, 217, 217);"&gt;example@passport.com&lt;/span&gt;&lt;span&gt;17262740.1050826919.32308\r\n&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;lt;&amp;lt;&amp;lt; USR 1 OK example@passport.com Example%20Name&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;lt;o&amp;gt; Continue SB Session . . .&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;USR认证时携带两个参数，第一个参数是当前用户，第二个参数即是前面的XFR应答消息中携带的Key值。&lt;/p&gt;&lt;p&gt;3. ClientA发送CAL命令邀请ClientB&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;gt;&amp;gt;&amp;gt; CAL 2 &lt;span style="background-color: rgb(217, 217, 217);"&gt;name_123@hotmail.com&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; CAL 2 RINGING 11752013&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;PS：服务器的CAL应答是等成功邀请上ClientB后才回应的，如上图所示。但ClientA感知不到这个过程，故这里就放在一块儿了。&lt;/p&gt;&lt;p&gt;4. NS发送RNG命令通知ClientB参加会话，ClientB根据RNG命令中SessionBoard地址，并发送ANS命令进行身份认证。&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 170, 0); font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; RNG &lt;span style="background-color: yellow;"&gt;11752013&lt;/span&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;207.46.108.38:1863&lt;/span&gt; CKI &lt;span style="background-color: rgb(217, 217, 217);"&gt;849102291.520491113&lt;/span&gt; example@passport.com Example%20Name&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; Client Connects to 207.46.108.38 1863 (Switchboard)&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; ANS 1 name_123@hotmail.com 849102291.520491113 &lt;span style="background-color: yellow;"&gt;11752013&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; IRO 1 1 2 example@passport.com Mike&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; IRO 1 2 2 myname@msn.com My%20Name&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; ANS 1 OK&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; Continue SB Session . . .&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;RNG命令有5个参数，前三个参数和XFR应答的三个参数意义一样，后面两个参数就是邀请方的账户和昵称。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;ClientB发送的ANSr认证有三个参数，前两个和发起方的USR认证一样，分别是账户和认证Key值，第三个参数则是RNG通知消息的TrID。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;发送认证信息后，会收到SB服务器的IRO通知消息，标明当前会话中的当前用户。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;从这个协议中不难看出，MSN协议设计时就考虑了多方通信的支持的，只要重复3,4步即可，要实现多方通信主要这里就不累述了。&lt;/p&gt;&lt;p&gt;从常见会话过程中可以看出，建立一个会话时，客户端分为主动连接和被动连接两种，主动连接方主要完成1、2、3这三步，而被动连接方主要完成第4步。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;退出会话&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;退出会话交互过程如下：&lt;/p&gt;&lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/TianFang/201205/201205061531415825.png" /&gt;&lt;/p&gt;&lt;p&gt;1. 主动退出方对SB发送OUT命令，SB则自动中断连接。&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; OUT&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; Switchboard Closes Connection&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;2. SB对会话中的其它成员发送BYE命令，通知其它成员会话有成员退出，如果只剩下一个成员，则和该成员的连接也会被中断。&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; BYE example@passport.com 1&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; Switchboard Closes Connection&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;另外，如果只有两个成员，且他们之间5分钟都没有活动，则服务器会对两个成员都发送BYE命令，此时的交互方式如下。&lt;/p&gt;&lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/TianFang/201205/201205061531414745.png" /&gt;&lt;/p&gt;&lt;p&gt;这时会话双方都是被动退出，交互过程和前面一样，就不累述了。&lt;/p&gt;&lt;p&gt;从前面的交互过程中可以看出，退出时也分为主动方和被动方：主动方需要发送OUT命令，被动方则需要响应BYE通知，还是比较简单的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;开始会话&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;MSN的对话都是在SB上进行的，并且对话信息都是通过MSG类型的消息发送的，它和我们打电话的过程非常类似。一个简单的对话过程如下：&lt;/p&gt;&lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/TianFang/201205/201205061531418890.png" /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="color: rgb(79, 129, 189); font-size: 10pt;"&gt;ClientA把消息发给SB&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;gt;&amp;gt;&amp;gt; MSG 4 N 133&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    MIME-Version: 1.0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    Content-Type: text/plain; charset=UTF-8&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    X-MMS-IM-Format: FN=Arial; EF=I; CO=0; CS=0; PF=22&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;    \r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    Hello! How are you? &lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; ACK 4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(79, 129, 189); font-family: 宋体; font-size: 12pt;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="color: rgb(79, 129, 189); font-size: 10pt;"&gt;SB服务器把消息转发给ClientB（如果是多方通话，则转发给其它的每个成员）&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;lt;&amp;lt;&amp;lt; MSG example@passport.com Mike 133&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    MIME-Version: 1.0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    Content-Type: text/plain; charset=UTF-8&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    X-MMS-IM-Format: FN=Arial; EF=I; CO=0; CS=0; PF=22&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;    \r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;    Hello! How are you?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(79, 129, 189); font-family: 宋体; font-size: 12pt;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="color: rgb(247, 150, 70); font-size: 10pt;"&gt;ClientB把回复消息发给SB&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="color: rgb(247, 150, 70); font-size: 10pt;"&gt;SB把ClientB的回复消息转发给ClientA（如果是多方通话，则转发给其它的每个成员）&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;从上可以看出，步骤3,4和步骤1,2是完全一样的，也就是说，&lt;span style="color: red;"&gt;MSN对话是不区分发送方和接收方的&lt;/span&gt;，所有交互都是通过SB转发，发送的消息都是单向的，接收消息都是靠通知而不是应答。这就意味着：发送方只能知道消息是否发送成功，并不能保证一定会应答，接收方收到消息通知时，并不要求要回应答。这一点和我们实际的交谈过程也是一样的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;除了类型为&lt;span style="color: maroon; font-family: Consolas; font-size: 9pt; background-color: white;"&gt;"text/plain"&lt;/span&gt;的对话内容通知消息外，另外一个比较常用的通知为那种常见的"xxx 正在输入&amp;#8230;"的通知，这个消息的格式为：&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MIME-Version: 1.0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Content-Type: text/x-msmsgscontrol&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TypingUser: example@passport.com&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;如果要实现一个较为友好的客户端，需要响应和发送此消息。&lt;/p&gt;&lt;p&gt;由于我最初只打算实现个MSN机器人，除了这两个消息外，其它的消息（如闪屏震动，文件发送等）我都没有实现，它们的处理方式也没有太大难度，如果感兴趣可以参考我前面的参考文献地址自行实现一下，就不要在留言中问我如何实现了。&lt;/p&gt;&lt;p&gt;代码实现：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('0b76d599-b776-434f-88e9-2a6f314b336d')"&gt;&lt;img style="display: none;" id="code_img_opened_0b76d599-b776-434f-88e9-2a6f314b336d" class="code_img_opened" onclick="cnblogs_code_hide('0b76d599-b776-434f-88e9-2a6f314b336d',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_0b76d599-b776-434f-88e9-2a6f314b336d" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;Conversation&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;MsnMessage&amp;gt;&amp;nbsp;MessageNotify&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;StateNotify&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;LogoutNotify&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MsnServer&amp;nbsp;sb;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;Conversation(MsnServer&amp;nbsp;sb)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.sb&amp;nbsp;=&amp;nbsp;sb;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MessageNotify&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt;&amp;nbsp;msg&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;in&lt;/span&gt;&amp;nbsp;sb.NotifyMsgs&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;where&lt;/span&gt;&amp;nbsp;msg.Headers.ContainsKey(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Content-Type&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;msg.Headers[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Content-Type&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;].StartsWith(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;text/plain&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt;&amp;nbsp;msg;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StateNotify&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt;&amp;nbsp;msg&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;in&lt;/span&gt;&amp;nbsp;sb.NotifyMsgs&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;where&lt;/span&gt;&amp;nbsp;msg.Headers.ContainsKey(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Content-Type&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;msg.Headers[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Content-Type&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;].StartsWith(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;text/x-msmsgscontrol&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt;&amp;nbsp;msg.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LogoutNotify&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt;&amp;nbsp;notify&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;in&lt;/span&gt;&amp;nbsp;sb.NotifyCmds&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;where&lt;/span&gt;&amp;nbsp;notify.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;BYE&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt;&amp;nbsp;notify.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MessageNotify.Subscribe(async&amp;nbsp;(msg)&amp;nbsp;=&amp;gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.White,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;###&amp;nbsp;Recv:&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;msg.Content);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;Send(&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;(msg.Content.Reverse().ToArray()),&amp;nbsp;msg.Headers);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StateNotify.Subscribe(account&amp;nbsp;=&amp;gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.White,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.Format(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;#-#&amp;nbsp;{0}&amp;nbsp;is&amp;nbsp;typing&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;account));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;Test();&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;async&amp;nbsp;void&amp;nbsp;Test()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;Invite("tianfangxyz@msn.com");&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;SendMessage("Hello!&amp;nbsp;How&amp;nbsp;are&amp;nbsp;you?");&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;}&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;MsnCommand&amp;gt;&amp;nbsp;Invite(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;user)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;await&amp;nbsp;sb.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;CAL&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;user);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;Task&amp;lt;MsnCommand&amp;gt;&amp;nbsp;SendMessage(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;content,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;font&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Arial&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;&amp;nbsp;size&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;22&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Requires(!&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.IsNullOrEmpty(content));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;headers&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;headers[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;MIME-Version&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;1.0&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;headers[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Content-Type&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;text/plain;&amp;nbsp;charset=UTF-8&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;headers[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;X-MMS-IM-Format&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.Format(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;FN={0};&amp;nbsp;EF=I;&amp;nbsp;CO=0;&amp;nbsp;CS=0;&amp;nbsp;PF={1}&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;font,&amp;nbsp;size);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;Send(content,&amp;nbsp;headers);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;MsnCommand&amp;gt;&amp;nbsp;Send(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;content,&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;,&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;headers)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Requires(headers&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;MsnMessage(MsnServer.NewTransactionId(),&amp;nbsp;headers,&amp;nbsp;content);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;await&amp;nbsp;sb.SendAsync(msg);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;68&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;69&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;70&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;Conversation&amp;gt;&amp;nbsp;CreateAsync(MsnServer&amp;nbsp;ns,&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;me)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;71&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;72&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Requires((ns&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(!&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.IsNullOrWhiteSpace(me)));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;73&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;74&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;reply&amp;nbsp;=&amp;nbsp;await&amp;nbsp;ns.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;XFR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;SB&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;75&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;hostAndPort&amp;nbsp;=&amp;nbsp;reply.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;76&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;key&amp;nbsp;=&amp;nbsp;reply.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;3&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;77&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;78&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;sb&amp;nbsp;=&amp;nbsp;await&amp;nbsp;MsnServer.CreateAsync(hostAndPort);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;79&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;sb.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;USR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;me,&amp;nbsp;key);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;80&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;81&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Conversation(sb);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;82&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;83&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;84&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;Conversation&amp;gt;&amp;nbsp;GetInvitations(MsnServer&amp;nbsp;ns,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;me)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;85&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;86&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;conversations&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt;&amp;nbsp;cmd&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;in&lt;/span&gt;&amp;nbsp;ns.NotifyCmds&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;87&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;where&lt;/span&gt;&amp;nbsp;cmd.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;RNG&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;88&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt;&amp;nbsp;conversation&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;in&lt;/span&gt;&amp;nbsp;Observable.FromAsync(()&amp;nbsp;=&amp;gt;&amp;nbsp;Conversation.CreateAsync(cmd,&amp;nbsp;me))&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;89&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt;&amp;nbsp;conversation;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;90&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;conversations.Subscribe();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;91&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;conversations;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;92&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;93&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;94&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;Conversation&amp;gt;&amp;nbsp;CreateAsync(MsnCommand&amp;nbsp;rng,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;me)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;95&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;96&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;hostAndPort&amp;nbsp;=&amp;nbsp;rng.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;97&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;id&amp;nbsp;=&amp;nbsp;(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;)rng.TransactionId;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;98&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;key&amp;nbsp;=&amp;nbsp;rng.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;2&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;99&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;100&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.White,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;ProcessInvitation:&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;hostAndPort);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;101&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;sb&amp;nbsp;=&amp;nbsp;await&amp;nbsp;MsnServer.CreateAsync(hostAndPort);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;102&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;sb.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;ANS&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;me,&amp;nbsp;key,&amp;nbsp;id);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;103&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Conversation(sb);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;104&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;105&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;到此我的MSN系列文章基本完结了，由于时间和精力有限，并不打算继续深入研究和完善。相关代码我基本都在文中已经贴出来了，总共也就3百行左右，非常简单。我实现代码只是为了练习Async编程，因此只实现了一个雏形，并不完善，如果在项目中需要实现MSN协议建议使用MSNSharp等开源库，我并不打算放出完整的工程下载，文章写完后相关代码即刻删除，本地也不会保留，请勿留言索取。&lt;/p&gt;&lt;p&gt;如果文中关于MSN协议的说明有误，欢迎留言指正。但如果是使用本文代码中遇到了问题，请不要留言求助，我没有足够的精力来一一指正，望见谅。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;img src="http://www.cnblogs.com/TianFang/aggbug/2485986.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/05/06/2485986.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/05/06/2485607.html</id><title type="text">用C#实现MSN客户端（四）</title><summary type="text">前面的文章里已经介绍了如何实现用户登录，本文中主要解决目前遗留下的一个问题：看到远端好友状态和让远端好友看到你的状态。一、联系人同步要看到远端好友的状态，首先需要进行的一步就是联系人同步。联系人同步主要是通过SYN命令来进行的，SYN命令格式如下：&gt;&gt;&gt; SYN 1 0\r\n&lt;&lt;&lt; SYN 1 2 1\r\n SYN命令只有一个参数，就是当前的同步序号，如果传0即可实现全同步，传大于0的数字时可以实现增量同步，当前同步到的最新序号可以从应答中获取。服务器收到SYN命令后，然后就会把当前联系人的设置通过通知的方式一一发送过来，一个示例如下：&gt;&gt;&amp;</summary><published>2012-05-06T01:35:00Z</published><updated>2012-05-06T01:35:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/05/06/2485607.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/05/06/2485607.html"/><content type="html">&lt;p&gt;前面的文章里已经介绍了如何实现用户登录，本文中主要解决目前遗留下的一个问题：看到远端好友状态和让远端好友看到你的状态。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;一、联系人同步&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;要看到远端好友的状态，首先需要进行的一步就是联系人同步。联系人同步主要是通过SYN命令来进行的，SYN命令格式如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt;&amp;gt;&amp;gt; SYN 1 &lt;span style="background-color: rgb(217, 217, 217);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; SYN 1 &lt;span style="background-color: rgb(217, 217, 217);"&gt;2&lt;/span&gt; 1&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;SYN命令只有一个参数，就是当前的同步序号，如果传0即可实现全同步，传大于0的数字时可以实现增量同步，当前同步到的最新序号可以从应答中获取。&lt;/p&gt;&lt;p&gt;服务器收到SYN命令后，然后就会把当前联系人的设置通过通知的方式一一发送过来，一个示例如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt;&amp;gt;&amp;gt; SYN 1 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; SYN 1 139 5 4&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; GTC A&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BLP AL&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PRP PHH 01%20234&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PRP PHM 56%20789&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 0 Other%20Contacts 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 1 Coworkers 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 2 Friends 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 3 Family 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal1@passport.com principal1 4&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal2@passport.com principal2 10&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal3@passport.com principal3 11 1,3&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal4@passport.com principal4 11 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BPR PHH 01%20234&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BPR MOB Y&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal5@passport.com principal5 12&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal6@passport.com principal6 11 2&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BPR PHW 45%206789&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;由此可见，这里的通知还是比较多的，有GTC、BLP、LSG、LST等，这里就不一一介绍了，要详细了解的话可以看一下这个网页：http://www.hypothetic.org/docs/msn/index.php&lt;/p&gt;&lt;p&gt;由于通知消息是异步发送的，这里就存在一个不知道什么时候结束的问题。我这里的做法是：在发送SYN命令后，紧跟着发送一个Ping命令PNG，这样，可以简单的认为收到QNG时同步已经完成，此时交互如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt;&amp;gt;&amp;gt; SYN 1 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; SYN 1 139 5 4&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="background-color: rgb(217, 217, 217);"&gt;&amp;gt;&amp;gt;&amp;gt; PNG&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; GTC A&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BLP AL&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PRP PHH 01%20234&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PRP PHM 56%20789&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 0 Other%20Contacts 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 1 Coworkers 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 2 Friends 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LSG 3 Family 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal1@passport.com principal1 4&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal2@passport.com principal2 10&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal3@passport.com principal3 11 1,3&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal4@passport.com principal4 11 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BPR PHH 01%20234&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BPR MOB Y&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal5@passport.com principal5 12&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; LST principal6@passport.com principal6 11 2&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; BPR PHW 45%206789&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;&amp;lt;&amp;lt;&amp;lt; QNG&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;不过MSN协议并没有规定QNG一定会在SYN通知完成后才通知，这种做法并不一定可靠，一般情况下貌似也没有什么大问题。&lt;/p&gt;&lt;p&gt;前面已经介绍过，SYNC的应答通知有许多种类型，要完全实现还是比较麻烦的。另外，要实现完善的话，只靠这个通知有时还不够，往往还需要根据用户人的账户名称获取详细信息。由于时间有限，我只弄了一个同步所有人的简单实现。也没有对同步结果进行任何处理。请看本文的朋友不要进一步询问相关问题，大可自己参考前面提到的那个网页自行实现。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('0da393c9-462d-4f28-887e-1a9b0a1c0b85')"&gt;&lt;img style="display: none;" id="code_img_opened_0da393c9-462d-4f28-887e-1a9b0a1c0b85" class="code_img_opened" onclick="cnblogs_code_hide('0da393c9-462d-4f28-887e-1a9b0a1c0b85',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_0da393c9-462d-4f28-887e-1a9b0a1c0b85" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;Sync&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;nbsp;SyncAll(MsnServer&amp;nbsp;server)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;TODO&amp;nbsp;增量同步&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;accounts&amp;nbsp;=&amp;nbsp;server.ReceiveUntilPingBack();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;accounts.Subscribe(i&amp;nbsp;=&amp;gt;&amp;nbsp;Debug.Write(ConsoleColor.Gray,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;i));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;server.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;SYN&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;server.SendPingAsync();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;accounts;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;13&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;二．接收好友状态变化&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步完联系人后，所有的联系人默认都是离线状态。对于那些非离线状态的联系人，服务器会通过NLN，ILN，FLN命令来通知联系人状态的变化。一个状态通知的示例如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; ILN &lt;span style="color: red;"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;AWY&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="color: rgb(0, 176, 240);"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;example@passport.com&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="color: rgb(0, 32, 96);"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;example%20display%20name&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="color: rgb(192, 80, 77);"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;268435492&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;它有四个参数，其中第一个参数表示当前的状态，目前MSN支持如下几种状态：&lt;/p&gt;&lt;ul style="margin-left: 43pt;"&gt;&lt;li&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: red; font-family: Consolas;"&gt;&lt;strong&gt;NLN&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt; - &lt;/span&gt;&lt;span style="color: rgb(102, 51, 153);"&gt;&lt;span style="font-family: 宋体;"&gt;有空&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;(Available)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: red; font-family: Consolas;"&gt;&lt;strong&gt;BSY&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt; - &lt;/span&gt;&lt;span style="color: rgb(102, 51, 153); font-family: 宋体;"&gt;忙碌&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;(&lt;span style="color: rgb(102, 51, 153);"&gt;Busy)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: red; font-family: Consolas;"&gt;&lt;strong&gt;IDL&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt; - &lt;/span&gt;&lt;span style="color: rgb(102, 51, 153); font-family: 宋体;"&gt;发呆&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;(&lt;span style="color: rgb(102, 51, 153);"&gt;Idle)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: red; font-family: Consolas;"&gt;&lt;strong&gt;BRB&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt; &amp;#8211; &lt;/span&gt;&lt;span style="color: rgb(102, 51, 153); font-family: 宋体;"&gt;马上回来&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;(&lt;span style="color: rgb(102, 51, 153);"&gt;Be Right Back)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: red; font-family: Consolas;"&gt;&lt;strong&gt;AWY&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt; &amp;#8211; &lt;/span&gt;&lt;span style="color: rgb(102, 51, 153); font-family: 宋体;"&gt;离开&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;(&lt;span style="color: rgb(102, 51, 153);"&gt;Away)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: red; font-family: Consolas;"&gt;&lt;strong&gt;PHN&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt; &amp;#8211; &lt;/span&gt;&lt;span style="color: rgb(102, 51, 153); font-family: 宋体;"&gt;电话中&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;(&lt;span style="color: rgb(102, 51, 153);"&gt;On the Phone)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: red; font-family: Consolas;"&gt;&lt;strong&gt;LUN&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt; &amp;#8211; &lt;/span&gt;&lt;span style="color: rgb(102, 51, 153); font-family: 宋体;"&gt;外出就餐&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;(&lt;span style="color: rgb(102, 51, 153);"&gt;Out to Lunch)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color: red; font-size: 9pt;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;strong&gt;HDN &lt;/strong&gt;&lt;span style="color: rgb(102, 51, 153);"&gt;&amp;#8211; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;隐身&lt;/span&gt;&lt;span style="color: rgb(102, 51, 153); font-family: Consolas;"&gt;(Hidden)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;第二个参数是用户账号，第三个参数是昵称（不完整），第四个参数是ClientID。其内容具体参看&lt;a href="http://www.hypothetic.org/docs/msn/notification/presence.php"&gt;http://www.hypothetic.org/docs/msn/notification/presence.php&lt;/a&gt;的Client Identification numbers一节，这里就不详细介绍了。&lt;/p&gt;&lt;p&gt;除了ILN外，&lt;/p&gt;&lt;p&gt;&lt;strong&gt;三. 设置我的状态&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;设置自己的状态主要通过CHG命令设置，示例如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt;&amp;gt;&amp;gt; CHG 12 NLN 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; CHG 12 NLN 0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;CHG命令有两个参数，第一个参数是状态，第二个是ClientID。设置成功后，服务器会回一个CHG应答。如果过于频繁设置状态，则会收到&amp;nbsp;&lt;a href="http://www.hypothetic.org/docs/msn/reference/error_list.php"&gt;800错误&lt;/a&gt;&amp;nbsp;。&lt;/p&gt;&lt;p&gt;代码附上：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('71a6685d-7dcf-4d6b-abce-3821144e197a')"&gt;&lt;img style="display: none;" id="code_img_opened_71a6685d-7dcf-4d6b-abce-3821144e197a" class="code_img_opened" onclick="cnblogs_code_hide('71a6685d-7dcf-4d6b-abce-3821144e197a',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_71a6685d-7dcf-4d6b-abce-3821144e197a" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;enum&lt;/span&gt;&amp;nbsp;State&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AWY,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;离开&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NLN,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;可用&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BSY,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;忙碌&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IDL,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;发呆&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BRB,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;马上回来&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PHN,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;打电话&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LUN,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;外出就餐&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HDN,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;隐身&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;12&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;StateMgr&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;State&amp;nbsp;State&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;16&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MsnServer&amp;nbsp;server;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;StateMgr(MsnServer&amp;nbsp;server,&amp;nbsp;State&amp;nbsp;state&amp;nbsp;=&amp;nbsp;State.NLN)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.server&amp;nbsp;=&amp;nbsp;server;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProcessStateChgNotify();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;22&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SetState(state);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;25&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;async&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&amp;nbsp;SetState(State&amp;nbsp;value)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;27&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.State&amp;nbsp;==&amp;nbsp;value)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;30&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.State&amp;nbsp;=&amp;nbsp;value;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;server.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;CHG&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;State&amp;nbsp;,&lt;span style="color: rgb(128, 0, 128);"&gt;6&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;34&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&amp;nbsp;ProcessStateChgNotify()&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;notify&amp;nbsp;=&amp;nbsp;server.NotifyCmds;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;38&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;39&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notify.Where(i&amp;nbsp;=&amp;gt;&amp;nbsp;(i.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;FLN&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&amp;nbsp;||&amp;nbsp;(i.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;NLN&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)).Subscribe(i&amp;nbsp;=&amp;gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;40&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;account&amp;nbsp;=&amp;nbsp;i.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;42&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.Cyan,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;account&amp;nbsp;+&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;离线了&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;43&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notify.Where(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;ILN&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;).Subscribe(i&amp;nbsp;=&amp;gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;46&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;state&amp;nbsp;=&amp;nbsp;i.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;account&amp;nbsp;=&amp;nbsp;i.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;48&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;name&amp;nbsp;=&amp;nbsp;i.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;2&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;49&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.Cyan,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;account&amp;nbsp;+&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;状态变为&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;state);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;50&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;51&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;52&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TianFang/aggbug/2485607.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/05/06/2485607.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/04/25/2470599.html</id><title type="text">用C#实现MSN客户端（三）</title><summary type="text">一、MSN中的Ping在基于TCP的协议中，一般都会都会设计Ping命令来检测并踢掉僵死的连接，从而节省服务器资源。在成功登陆到服务器后，一般立即会收到到服务器发送的Ping命令CHL，如过不进行正确的应答的话，则会被服务器踢掉。为了后面的功能能正常运行，首先我们必须学习一下MSN的Ping命令。MSN协议中的Ping命令有两种：服务器端发送的和客户端发送的。客户端发送的Ping命令非常简单：客户端发送PNG命令，服务器应答QNG，都不携带任何参数。&gt;&gt;&gt; PNG/r/n&lt;&lt;&lt; QNG/r/n 除了客户端Ping服务器外，服务器也会不定时（一般登录后就会收到</summary><published>2012-04-25T13:59:00Z</published><updated>2012-04-25T13:59:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/04/25/2470599.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/04/25/2470599.html"/><content type="html">&lt;p&gt;&lt;strong&gt;一、MSN中的Ping&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在基于TCP的协议中，一般都会都会设计Ping命令来检测并踢掉僵死的连接，从而节省服务器资源。在成功登陆到服务器后，一般立即会收到到服务器发送的Ping命令CHL，如过不进行正确的应答的话，则会被服务器踢掉。为了后面的功能能正常运行，首先我们必须学习一下MSN的Ping命令。&lt;/p&gt;&lt;p&gt;MSN协议中的Ping命令有两种：服务器端发送的和客户端发送的。客户端发送的Ping命令非常简单：客户端发送PNG命令，服务器应答QNG，都不携带任何参数。&lt;br /&gt;&lt;span style="color: #0000aa; font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;gt;&amp;gt;&amp;gt; PNG&lt;span style="color: #cccccc;"&gt;/r/n&lt;br /&gt;&lt;span style="color: #00aa00;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; QNG&lt;span style="color: #cccccc;"&gt;/r/n&lt;span style="color: #333333;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;除了客户端Ping服务器外，服务器也会不定时（一般登录后就会收到一次）对客户端发送Ping命令CHL。CHL命令之间没有固定周期，它包含两个参数：第一个总会是0，第二个被称作"Challenge String"，客户端会根据它来生成应答。CHL命令格式如下：&lt;br /&gt;&lt;span style="color: #00aa00; font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; CHL 0 &lt;/span&gt;&lt;span style="background-color: #d9d9d9;"&gt;15570131571988941333&lt;/span&gt;&lt;span style="color: #cccccc; background-color: white;"&gt;/r/n&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;接收Challenge命令后，必须在50秒内发送应答命令QRY到服务器，否则将被断开。应答命令QRY格式如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: #00aa00; font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;&amp;lt;&amp;lt; CHL 0 15570131571988941333&lt;span style="color: #cccccc;"&gt;/r/n&lt;br /&gt;&lt;span style="color: #00aa00;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000aa;"&gt;&amp;gt;&amp;gt;&amp;gt; QRY 1049 &lt;span style="background-color: #d9d9d9;"&gt;msmsgs@msnmsgr.com&lt;/span&gt; 32&lt;span style="color: #cccccc;"&gt;/r/n&lt;span style="color: #0000aa;"&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #00aa00;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000aa;"&gt;&lt;strong&gt;&lt;span style="background-color: #d9d9d9;"&gt;8f2f5a91b72102cd28355e9fc9000d6e&lt;/span&gt;&amp;nbsp;&lt;span style="color: #00aaaa;"&gt;(no newline)&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: #333333;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;QRY命令主要有三个参数，第一个参数是客户端ID，第二个参数是32，第三个参数是客户端应答字符串。其实前面介绍过：QRY是一个有效载荷命令，它的第二个参数是后面的内容（应答字符串），因为应答字符串长度是32，因此第二个参数也就固定为32。因此需要我们填充的是第一个参数客户端ID和第三个参数应答字符串。下面就介绍一下这两个参数的生成方式。&lt;/p&gt;&lt;p&gt;首先看一张表:&lt;/p&gt;&lt;div&gt;&lt;table style="border-collapse: collapse;" border="0" align="center"&gt;&lt;colgroup&gt;&lt;col style="width: 284px;"&gt;&lt;col style="width: 284px;"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td style="border-width: 1pt medium; border-style: solid none; border-color: #c0504d currentColor; padding-right: 7px; padding-left: 7px;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;&lt;strong&gt;客户端ID&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-width: 1pt medium; border-style: solid none; border-color: #c0504d currentColor; padding-right: 7px; padding-left: 7px;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;&lt;strong&gt;客户端标识码&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background: #efd3d2;"&gt;&lt;td style="padding-right: 7px; padding-left: 7px; border-right-color: currentColor; border-left-color: currentColor; border-right-width: medium; border-left-width: medium; border-right-style: none; border-left-style: none;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;&lt;strong&gt;msmsgs@msnmsgr.com&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="padding-right: 7px; padding-left: 7px; border-right-color: currentColor; border-left-color: currentColor; border-right-width: medium; border-left-width: medium; border-right-style: none; border-left-style: none;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;Q1P7W2E4J9R8U3S5&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding-right: 7px; padding-left: 7px;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;&lt;strong&gt;PROD0038W!61ZTF9&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="padding-right: 7px; padding-left: 7px;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;VT6PX?UQTM4WM%YR&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background: #efd3d2;"&gt;&lt;td style="padding-right: 7px; padding-left: 7px; border-right-color: currentColor; border-left-color: currentColor; border-right-width: medium; border-left-width: medium; border-right-style: none; border-left-style: none;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;&lt;strong&gt;PROD0058#7IL2{QD&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="padding-right: 7px; padding-left: 7px; border-right-color: currentColor; border-left-color: currentColor; border-right-width: medium; border-left-width: medium; border-right-style: none; border-left-style: none;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;QHDCY@7R1TB6W?5B&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding-right: 7px; padding-left: 7px; border-bottom-color: #c0504d; border-bottom-width: 1pt; border-bottom-style: solid;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;&lt;strong&gt;PROD0061VRRZH@4F&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="padding-right: 7px; padding-left: 7px; border-bottom-color: #c0504d; border-bottom-width: 1pt; border-bottom-style: solid;"&gt;&lt;p&gt;&lt;span style="color: #943634; font-size: 10pt;"&gt;JXQ6J@TUOGYV@N0M&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;其中客户端ID可以取上表中的一个（貌似也不是任取一个就可以的），而应答字符串则是CHL命令的Challenge String参数和客户端标识码的MD5值（这个也是为什么长度总是32的原因）。&lt;/p&gt;&lt;p&gt;例如，对于前面的CHL命令，我们取客户端字符串为&lt;span style="color: #0000aa; font-family: Consolas; font-size: 9pt; background-color: #d9d9d9;"&gt;msmsgs@msnmsgr.com&lt;/span&gt;，对应的客户端标识码为&lt;span style="color: red; font-family: Consolas; font-size: 9pt; background-color: #d9d9d9;"&gt;Q1P7W2E4J9R8U3S5&lt;/span&gt;，则对应的应答码的为：MD5(&lt;span style="color: #00aa00;"&gt;&lt;span style="font-family: Consolas; font-size: 9pt; background-color: #d9d9d9;"&gt;15570131571988941333 + &lt;span style="color: red;"&gt;Q1P7W2E4J9R8U3S5&lt;/span&gt;&lt;/span&gt;) = &lt;span style="color: #0000aa; font-family: Consolas; font-size: 9pt; background-color: #d9d9d9;"&gt;&lt;strong&gt;8f2f5a91b72102cd28355e9fc9000d6e&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;有了上面的基础后，用C#实现一个客户端的主动Ping命令和对服务器的ping命令自动应答就十分简单了，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('ab05637b-385e-4411-a0af-046af1156a78')"&gt;&lt;img style="display: none;" id="code_img_opened_ab05637b-385e-4411-a0af-046af1156a78" class="code_img_opened" onclick="cnblogs_code_hide('ab05637b-385e-4411-a0af-046af1156a78',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_ab05637b-385e-4411-a0af-046af1156a78" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&amp;nbsp;Ping&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;nbsp;SendPingAsync(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&amp;nbsp;MsnServer&amp;nbsp;server)&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;server.SendAsync(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&amp;nbsp;MsnCommand(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;PNG&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;MsnCommand&amp;gt;&amp;nbsp;ReceiveUntilPingBack(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&amp;nbsp;MsnServer&amp;nbsp;server)&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&amp;nbsp;server.NotifyCmds.TakeWhile(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.CmdType&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;QNG&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;应答服务器的ping命令&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: #808080;"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&amp;nbsp;RegistPingReply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&amp;nbsp;MsnServer&amp;nbsp;server)&lt;br /&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt;&amp;nbsp;clientId&amp;nbsp;=&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;PROD0061VRRZH@4F&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt;&amp;nbsp;clientCode&amp;nbsp;=&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JXQ6J@TUOGYV@N0M&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt;&amp;nbsp;md5&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&amp;nbsp;System.Security.Cryptography.MD5CryptoServiceProvider();&lt;br /&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;server.NotifyCmds.Where(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;CHL&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Subscribe(async&amp;nbsp;(cmd)&amp;nbsp;=&amp;gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt;&amp;nbsp;data&amp;nbsp;=&amp;nbsp;md5.ComputeHash(UnicodeEncoding.UTF8.GetBytes(cmd.Paras[&lt;span style="color: #800080;"&gt;0&lt;/span&gt;]&amp;nbsp;+&amp;nbsp;clientCode));&lt;br /&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt;&amp;nbsp;replyKey&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Join(&lt;span style="color: #800000;"&gt;""&lt;/span&gt;,&amp;nbsp;data.Select(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.ToString(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;x2&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)));&lt;br /&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt;&amp;nbsp;replyCmd&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&amp;nbsp;MsnCommand(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;QRY&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;,&amp;nbsp;clientId,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;32&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)&amp;nbsp;{&amp;nbsp;Content&amp;nbsp;=&amp;nbsp;replyKey&amp;nbsp;};&lt;br /&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;server.SendAsync(replyCmd);&lt;br /&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;二、退出登录&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;介绍完Ping后，顺带介绍一下上章中忘记介绍的退出登录。&lt;/p&gt;&lt;p&gt;退出登录最简单的方法就是正常关闭socket连接，这种方式也是非常简单有效的。但还有一种方式是对服务器发送OUT指令，服务器受到OUT指令后会主动关闭socket连接。&lt;br /&gt;&lt;span style="color: #0000aa; font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; OUT&lt;span style="color: #cccccc;"&gt;/r/n&lt;br /&gt;&lt;span style="color: #00aaaa;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;o&amp;gt; Server closes connection&lt;span style="color: #333333;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;除了上面介绍的客户端主动退出登录外，服务器有时也会发送OUT指令强制客户端退出登录。主要有如下两种情况： &lt;/p&gt;&lt;p&gt;1. 当服务器要进行维护时，将会发送OUT SSD &amp;#8212; server shutting down，发送后就立即关闭连接。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000aa; font-family: Consolas; font-size: 9pt;"&gt;&amp;lt;&amp;lt;&amp;lt; OUT SSD&lt;span style="color: #cccccc;"&gt;/r/n&lt;br /&gt;&lt;span style="color: #00aaaa;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;o&amp;gt; Server closes connection&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;2.&lt;span style="color: #333333; background-color: white;"&gt;&lt;span style="font-size: 10pt;"&gt;当有人在别处用你的账号登录时，原来的连接将被关闭，新连接将被建立。关闭连接前，&lt;span style="font-family: Arial;"&gt;NS&lt;/span&gt;将给客户端发送&lt;span style="font-family: Arial;"&gt;OUT&lt;/span&gt;命令并携带参数&lt;span style="font-family: Arial;"&gt;OTH&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000aa; font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;lt; OUT OTH&lt;span style="color: #cccccc;"&gt;/r/n&lt;br /&gt;&lt;span style="color: #00aaaa;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;o&amp;gt; Server closes connection&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #333333; background-color: white;"&gt;最后附带一下代码的实现。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('bf8b8679-e9df-49be-8f94-a0c0919a800c')"&gt;&lt;img style="display: none;" id="code_img_opened_bf8b8679-e9df-49be-8f94-a0c0919a800c" class="code_img_opened" onclick="cnblogs_code_hide('bf8b8679-e9df-49be-8f94-a0c0919a800c',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_bf8b8679-e9df-49be-8f94-a0c0919a800c" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&amp;nbsp;Logout&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&amp;nbsp;LogoutAsync(MsnServer&amp;nbsp;server)&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;server.SendAsync(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&amp;nbsp;MsnCommand(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OUT&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;GetLogoutNotify(MsnServer&amp;nbsp;server)&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;CmdType有SSD和OTH两种&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&amp;nbsp;server.NotifyCmds.FirstAsync(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OUT&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Select(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OTH&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;?&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;用户在其他地方登陆&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;:&amp;nbsp;&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;服务器故障&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #333333; background-color: white;"&gt;PS：本来打算在这篇文章中介绍一下如何实现设置和获取联系人的在线状态的，但由于如果不能正确实现对服务器的Ping应答的话，一般刚登上去就会被踢掉的，故先介绍一下。设置和获取联系人的功能待下篇文章中再介绍。&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TianFang/aggbug/2470599.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/04/25/2470599.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/04/22/2464693.html</id><title type="text">用C#实现MSN客户端（二）</title><summary type="text">上一篇文章里对MSN协议进行了简单的介绍，并实现了消息的解析，今天这里将简单地介绍一下如何实现MSN客户端登陆。</summary><published>2012-04-22T02:09:00Z</published><updated>2012-04-22T02:09:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/04/22/2464693.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/04/22/2464693.html"/><content type="html">&lt;p&gt;上一篇&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/04/20/2460777.html"&gt;文章&lt;/a&gt;里对MSN协议进行了简单的介绍，并实现了消息的解析，今天这里将简单地介绍一下如何实现MSN客户端登陆。&lt;/p&gt;&lt;p&gt;MSN会话的服务器一般称为通知服务器(Notification Server, NS)，但由于MSN用户比较多，因此采用的是分布式结构，通知服务器并不唯一。我们首先需要连接需要连接分派服务器（Dispatch Server, DS），获取通知服务器地址。大致步骤如下：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. 连接到&lt;span style="color: red;"&gt;messenger.hotmail.com:1863&lt;/span&gt;(Dispatch Server)，发送VER指令说明版本信息&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170); background-color: white;"&gt;&amp;lt;o&amp;gt; Connect: messenger.hotmail.com 1863&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; VER 0 MSNP8 CVR0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; VER 0 MSNP8 CVR0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. 发送CVR指令说明当前使用的环境&lt;/strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; CVR 2 0x0409 win 4.10 i386 MSNMSGR 5.0.0544 MSMSGS example@passport.com&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; CVR 2 6.0.0602 6.0.0602&amp;nbsp;1.0.0000http://download.microsoft.com/download/8/a/4/8a42bcae-f533-4468-b871-d2bc8dd32e9e/SETUP9x.EXE http://messenger.msn.com&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3. 发送USR命令进行初始认证，获取通知服务器地址发送USR说明身份&lt;/strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; USR 2 TWN &lt;span style="background-color: lightgrey;"&gt;I&lt;/span&gt; example@passport.com&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; &lt;span style="background-color: lightgrey;"&gt;XFR&lt;/span&gt; 2 NS &lt;span style="background-color: lightgrey;"&gt;207.46.106.145:1863&lt;/span&gt; 0 207.46.104.20:1863&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 170);"&gt;&lt;span style="background-color: white;"&gt;&amp;lt;o&amp;gt; Server Closes Connection&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;注意，&lt;/span&gt;USR命令的第二个参数为I，表示此时为初次认证（Initiating）。此时应答命令的类型是XFR，其中第二个参数（高亮部分）表示的是通知服务器地址。&lt;span style="color: rgb(51, 51, 51); font-family: Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;获取到通知服务器地址后，分派服务器将会自动关闭，客户端开始连接通知服务器。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;4. 重复上面的认证过程（注意把高亮的&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt; background-color: lightgrey;"&gt;example@passport.com&lt;/span&gt;替换成自己的用户名）&lt;span style="color: rgb(0, 170, 170); font-family: Consolas; font-size: 9pt;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 170);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&amp;lt;o&amp;gt; client connects to 207.46.106.35, port 1863&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; VER 1 MSNP8 CVR0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; VER 1 MSNP8 CVR0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; CVR 2 0x0409 win 4.10 i386 MSNMSGR 5.0.0544 MSMSGS &lt;span style="background-color: lightgrey;"&gt;example@passport.com&lt;/span&gt;/r/n&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; CVR 2 6.0.0602 6.0.0602&amp;nbsp;1.0.0000http://download.microsoft.com/download/8/a/4/8a42bcae-f533-4468-b871-d2bc8dd32e9e/SETUP9x.EXE http://messenger.msn.com.&lt;span style="color: rgb(204, 204, 204);"&gt; /r/n&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; USR 3 TWN I &lt;span style="background-color: lightgrey;"&gt;example@passport.com&lt;/span&gt;/r/n&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; &lt;span style="background-color: lightgrey;"&gt;USR&lt;/span&gt; 3 &lt;span style="background-color: rgb(217, 217, 217);"&gt;TWN&lt;/span&gt; S &lt;span style="background-color: rgb(217, 217, 217);"&gt;lc=1033,id=507,tw=40,fs=1,ru=http%3A%2F%2Fmessenger%2Emsn%2Ecom,ct=1062764229,kpp=1,kv=5,ver=2.1.0173.1,tpf=43f8a4c8ed940c04e3740be46c4d1619&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;此时&lt;/span&gt;USR&lt;/span&gt;的应答命令也是USR了（注意，它可能还是XFR，此时需要再次连接下一个NS了），它的第三个参数&lt;span style="background-color: lightgrey;"&gt;lc=1033&amp;#8230;&lt;/span&gt;就是当前用户的一个标识，一般称作Challenge String，用于后面的SSL 身份验证。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;5. 连接https://nexus.passport.com/rdr/pprdr.asp，获取认证服务器&lt;br /&gt;&lt;/strong&gt;&lt;span style="color: rgb(204, 204, 204); font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; Client connects to nexus.passport.com, port 443 (Passport Nexus)&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; GET /rdr/pprdr.asp HTTP/1.0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;/r/n&lt;br /&gt;&lt;/strong&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; HTTP/1.1 200 OK&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Server: Microsoft-IIS/5.0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Date: Mon, 02 Jun 2003 11:57:47 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Connection: close&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PassportURLs: DARealm=Passport.Net,DALogin=&lt;span style="color: red;"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;login.passport.com/login2.srf&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;,DAReg=http://register.passport.net/uixpwiz.srf,Properties=https://register.passport.net/editprof.srf,Privacy=http://www.passport.com/consumer/privacypolicy.asp,GeneralRedir=http://nexusrdr.passport.com/redir.asp,Help=http://memberservices.passport.net/memberservice.srf,ConfigVersion=11&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Content-Length: 0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Content-Type: text/html&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Cache-control: private&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;strong&gt;&amp;nbsp;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; nexus.passport.com closes connection&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;其中应答信息的DALogin=后面的部分就是认证服务器。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;6. 连接认证服务器，发送认证信息，获取令牌&lt;/strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; Client connects to login.passport.com, port 443&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; GET /login2.srf HTTP/1.1&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&amp;gt;&amp;gt;&lt;/strong&gt;&amp;gt; Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=&lt;span style="background-color: rgb(217, 217, 217);"&gt;example%40passport.com&lt;/span&gt;,pwd=&lt;span style="background-color: rgb(217, 217, 217);"&gt;password&lt;/span&gt;,&lt;span style="background-color: rgb(217, 217, 217);"&gt;lc=1033,id=507,tw=40,fs=1,ru=http%3A%2F%2Fmessenger%2Emsn%2Ecom,ct=1062764229,kpp=1,kv=5,ver=2.1.0173.1,tpf=43f8a4c8ed940c04e3740be46c4d1619&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 0, 170);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; Host: login.passport.com&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;strong&gt;/&lt;/strong&gt;r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;注意认证信息中高亮三个部分，前两个分别是用户名和密码，均采用URL编码，第三个是前面获取到的Challenge String&lt;/p&gt;&lt;p&gt;这个http请求一般会有三种结果，一个是302应答，重定向新的认证服务器。&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; HTTP/1.1 &lt;span style="color: red;"&gt;302 &lt;span style="color: rgb(0, 170, 0);"&gt;Found&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Server: Microsoft-IIS/5.0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Date: Mon, 02 Jun 2003 11:58:32 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PPServer: H: LAWPPLOG5C006&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Connection: close&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Content-Type: text/html&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Expires: Mon, 02 Jun 2003 11:57:32 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Cache-Control: no-cache&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; cachecontrol: no-store&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Pragma: no-cache&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Authentication-Info: Passport1.4 da-status=redir&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Location: &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red;"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;https://loginnet.passport.com/login2.srf?lc=1033&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;span style="background-color: white;"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;strong&gt;&amp;nbsp;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;此时就要连接到新的认证服务器，重复上面的过程。&lt;/p&gt;&lt;p&gt;另一种是401应答，认证失败。&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204); font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; HTTP/1.1 &lt;span style="color: red;"&gt;401 &lt;span style="color: rgb(0, 170, 0);"&gt;Unauthorized&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Server: Microsoft-IIS/5.0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Date: Mon, 02 Jun 2003 11:58:15 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PPServer: H: LAWPPIIS6B077&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Connection: close&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Content-Type: text/html&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Expires: Mon, 15 Sep 2003 07:57:14 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Cache-Control: no-cache&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; cachecontrol: no-store&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Pragma: no-cache&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PassportConfig: ConfigVersion=11&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; WWW-Authenticate: Passport1.4 da-status=failed,srealm=Passport.NET,ts=-3,prompt,cburl=http://www.passportimages.com/XPPassportLogo.gif,cbtxt=Type%20your%20e-mail%20address%20and%20password%20correctly.%20If%20you%20haven%E2%80%99t%20registered%20with%20.NET%20Passport%2C%20click%20the%20Get%20a%20.NET%20Passport%20link.&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Content-Length: 390&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n/r/n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;此时就没有继续进行下去的必要了，直接抛异常退出。&lt;/p&gt;&lt;p&gt;最后一种是我们所期望的200应答，认证成功。&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0); font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;strong&gt;&amp;lt;&amp;lt; HTTP/1.1 &lt;span style="color: red;"&gt;200 &lt;span style="color: rgb(0, 170, 0);"&gt;OK&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Server: Microsoft-IIS/5.0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Date: Mon, 02 Jun 2003 11:59:00 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; PPServer: H: LAWPPIIS6B061&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Connection: close&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Content-Type: text/html&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Expires: Mon, 02 Jun 2003 11:58:00 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Cache-Control: no-cache&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; cachecontrol: no-store&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Pragma: no-cache&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Set-Cookie: MSPSec1= ; expires=Thu, 30-Oct-1980 16:00:00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;GMT;domain=.passport.com;path=/;HTTPOnly= ;version=1&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Set-Cookie: MSPSec=5Cdd1SshOELpwqafsSuYSiDEuEtP1PUaX99YOZcaoJP3vkIn7DXozt868I7eJNjcWG; HTTPOnly= ; domain=.passport.com;path=/;secure=&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Set-Cookie: MSPAuth=5yDBU0BqvDa7UiY9W9nVEncRXCLD4gjLmtEr2XkunnafkOgdgG5x*CEpqe7MyZEOir*EiA1PbwLKzqCGO671TeTQ$$; HTTPOnly= ; domain=.passport.com;path=/&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Set-Cookie: MSPProf=5a0mKE6PKDsxz!*4apQt0amnQOGLYqcCm78ie!MmHq0KnAiIJM0z0Zajs8NL7ux7Ae0hnH5AAoB!zXIZ9jTA2rcQttC*RKKRsc9k7JflwThB!H0Qa*6ipGcdj5co6taPir; HTTPOnly= ; domain=.passport.com;path=/&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Set-Cookie: MSPVis=507;domain=.passport.com;path=/&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Set-Cookie: MSPPre=esqkk@hotmail.com; HTTPOnly= ; domain=.passport.com;path=/;Expires=Wed, 30-Dec-2037 16:00:00 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Set-Cookie: MSPShared= ; HTTPOnly= ; domain=.passport.com;path=/;Expires=Thu, 30-Oct-1980 16:00:00 GMT&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Authentication-Info: Passport1.4 da-status=success,tname=MSPAuth,tname=MSPProf,tname=MSPSec,from-PP='&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red;"&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;t=53*1hAu8ADuD3TEwdXoOMi08sD*2!cMrntTwVMTjoB3p6stWTqzbkKZPVQzA5NOt19SLI60PY!b8K4YhC!Ooo5ug$$&amp;amp;p=5eKBBC!yBH6ex5mftp!a9DrSb0B3hU8aqAWpaPn07iCGBw5akemiWSd7t2ot!okPvIR!Wqk!MKvi1IMpxfhkao9wpxlMWYAZ!DqRfACmyQGG112Bp9xrk04!BVBUa9*H9mJLoWw39m63YQRE1yHnYNv08nyz43D3OnMcaCoeSaEHVM7LpR*LWDme29qq2X3j8N&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0); background-color: white;"&gt;',ru=http://messenger.msn.com&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; Content-Length: 0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 170, 0);"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;strong&gt;&amp;nbsp;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;其中from-PP=头里面包含的信息即是用户的令牌，一般称为Ticket。&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;&lt;strong&gt;7. 返回到前面的NS服务器，继续发送USR命令进行认证。&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 170);"&gt;&lt;span style="font-family: Consolas; font-size: 9pt;"&gt;&lt;strong&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 170);"&gt;&amp;lt;o&amp;gt; Client authenticates itself with MS Passport&lt;br /&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;gt;&amp;gt;&amp;gt; USR 4 TWN &lt;span style="background-color: rgb(217, 217, 217);"&gt;S&lt;/span&gt;&lt;span style="background-color: rgb(217, 217, 217);"&gt;t=53*1hAu8ADuD3TEwdXoOMi08sD*2!cMrntTwVMTjoB3p6stWTqzbkKZPVQzA5NOt19SLI60PY!b8K4YhC!Ooo5ug$$&amp;amp;p=5eKBBC!yBH6ex5mftp!a9DrSb0B3hU8aqAWpaPn07iCGBw5akemiWSd7t2ot!okPvIR!Wqk!MKvi1IMpxfhkao9wpxlMWYAZ!DqRfACmyQGG112Bp9xrk04!BVBUa9*H9mJLoWw39m63YQRE1yHnYNv08nyz43D3OnMcaCoeSaEHVM7LpR*LWDme29qq2X3j8N&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;br /&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; USR 4 &lt;span style="background-color: rgb(217, 217, 217);"&gt;OK&lt;/span&gt; example@passport.com example%20display%20name 1 0&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;此时USR命令的第二个参数不再是I，而是S；第四个参数也不是用户名，而是前面获取的TICKET。而应答的第一个参数也不是前面的TWN，而是OK，后面两个参数则是当前用户名和昵称。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;代码实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;代码实现如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('e5ecf81c-808b-4736-8f08-9e3b901f63bf')"&gt;&lt;img style="display: none;" id="code_img_opened_e5ecf81c-808b-4736-8f08-9e3b901f63bf" class="code_img_opened" onclick="cnblogs_code_hide('e5ecf81c-808b-4736-8f08-9e3b901f63bf',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_e5ecf81c-808b-4736-8f08-9e3b901f63bf" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;Login&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;UserName&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;Password&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;Login(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;userName,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;password)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.UserName&amp;nbsp;=&amp;nbsp;userName;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.Password&amp;nbsp;=&amp;nbsp;password;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;11&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;Task&amp;lt;MsnServer&amp;gt;&amp;nbsp;Process(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;host&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;messenger.hotmail.com&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;&amp;nbsp;port&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;1863&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;session&amp;nbsp;=&amp;nbsp;await&amp;nbsp;MsnServer.CreateAsync(host,&amp;nbsp;port);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;15&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;session.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;VER&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;MSNP8&amp;nbsp;CVR0&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;session.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;CVR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;0x0804&amp;nbsp;win&amp;nbsp;5.1.2600&amp;nbsp;i386&amp;nbsp;MSNMSGR&amp;nbsp;7.0.0813&amp;nbsp;MSMSGS&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;UserName);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;reply&amp;nbsp;=&amp;nbsp;await&amp;nbsp;session.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;USR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;TWN&amp;nbsp;I&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;UserName);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;19&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;加速方法：中间可能会经过XFR重定位一次，保存重定位后的地址，下次直接从它启动，失败后再从messenger.hotmail.com获取&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;21&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Assume((reply.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;XFR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&amp;nbsp;||&amp;nbsp;(reply.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;USR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(reply.CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;XFR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;xfrEpData&amp;nbsp;=&amp;nbsp;reply.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;].Split(&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;await&amp;nbsp;Process(xfrEpData[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;],&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;.Parse(xfrEpData[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;]));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;27&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;await&amp;nbsp;session.SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;USR&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;TWN&amp;nbsp;S&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;await&amp;nbsp;GetTicket(reply.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;2&lt;/span&gt;]));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Assume(result.Paras[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;]&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;OK&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;30&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;session;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;33&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;Task&amp;lt;MsnServer&amp;gt;&amp;nbsp;ConnectAsync(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;userName,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;password)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Login(userName,&amp;nbsp;password).Process();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;38&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;39&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;Task&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;GetTicket(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;challengeStr)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;40&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;加速方法：保存DALoginUrl，下次启动或使用时直接读取保存的数据，失败后再从nexus.passport.com中更新&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;42&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;daLoginUrl&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;https://&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;await&amp;nbsp;SendRequestAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;https://nexus.passport.com/rdr/pprdr.asp&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;DALogin=(.+?),&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;43&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;authInfo&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.Format(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Passport1.4&amp;nbsp;OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger.msn.com,sign-in={0},pwd={1},{2}&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.HttpUtility.UrlEncode(UserName),&amp;nbsp;System.Web.HttpUtility.UrlEncode(Password),&amp;nbsp;challengeStr);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;46&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;await&amp;nbsp;SendRequestAsync(daLoginUrl,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;from-PP='(.+?)'&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;req&amp;nbsp;=&amp;gt;&amp;nbsp;{&amp;nbsp;req.Headers.Add(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;Authorization&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;authInfo);&amp;nbsp;});&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;48&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;49&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;50&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;Task&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;SendRequestAsync(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;url,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;matchResultExp&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;,&amp;nbsp;Action&amp;lt;HttpWebRequest&amp;gt;&amp;nbsp;reqHanlder&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;51&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;52&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;req&amp;nbsp;=&amp;nbsp;WebRequest.Create(url)&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt;&amp;nbsp;HttpWebRequest;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;53&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(reqHanlder&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;54&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;55&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reqHanlder(req);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;56&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;57&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;58&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.Gray,&amp;nbsp;url&amp;nbsp;+&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;\r\n&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;req.Headers);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;59&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;60&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;using&lt;/span&gt;&amp;nbsp;(&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;rsp&amp;nbsp;=&amp;nbsp;await&amp;nbsp;req.GetResponseAsync())&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;61&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;62&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;headers&amp;nbsp;=&amp;nbsp;rsp.Headers.ToString();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;63&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.Cyan,&amp;nbsp;headers);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;64&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;65&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(matchResultExp&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;headers;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;67&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;68&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;Regex.Match(headers,&amp;nbsp;matchResultExp).Groups[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;].Value;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;69&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;70&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;71&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;基本上只用几十行就可以实现登陆的主体功能，实现起来所花的时间远比看协议要少得多。它使用起来也非常简单，只有一个人口函数Login.ConnectAsync()，这里就不举例了。&lt;/p&gt;&lt;p&gt;另外，从这个流程可以看出，&lt;span style="color: rgb(192, 80, 77);"&gt;MSN客户端在认证过程中，经历了多次重定向，这个也是其登陆较慢的原因之一&lt;/span&gt;，在代码的注释中我已经列举了两种减少重定向次数，加速登陆的方法，但没有实现，感兴趣的朋友可以试着实现一下。&lt;/p&gt;&lt;p&gt;到此时，我们已经可以实现MSN客户端登陆了，但把这段代码执行后就会发现：&lt;span style="color: rgb(192, 80, 77);"&gt;即使用户认证成功，远端好友仍然看不到该用户的上线&lt;/span&gt;。实际上，完成用户认证只是万里长征的第一步，下一篇文章中将介绍如何改变用户的状态。&lt;/p&gt;   &lt;img src="http://www.cnblogs.com/TianFang/aggbug/2464693.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/04/22/2464693.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/04/20/2460777.html</id><title type="text">用C#实现MSN客户端（一）</title><summary type="text">清明的时候学习一下C# 5.0的新特性async，顺带用它实现了一个C#的MSN客户端，实现了简单的通话功能。 第一篇主要介绍了MSN消息的格式和解析方法。</summary><published>2012-04-20T15:39:00Z</published><updated>2012-04-20T15:39:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/04/20/2460777.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/04/20/2460777.html"/><content type="html">&lt;p&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;清明的时候学习一下C# 5.0的新特性async，顺带用它实现了一个C#的MSN客户端，实现了简单的通话功能。&lt;/p&gt;&lt;p&gt;MSN协议还是比较复杂的，不是两三天能完整实现的。由于工作较忙，加上MSN也只是一个小众产品，开发动力不足。本文的主要目的是介绍MSN协议基础和练习async编程，暂时没有打算完善其功能。如果后续有时间的话可能会进一步完善。文中所涉及到的主要流程、思路及关键算法都会在代码中贴出来，我也只实现了简单的通话功能，但还有大部分异常处理工作要做，本身就不是很完善。由于工作较忙，如果是代码实现过程中遇到的问题一般是不会解答的，请见谅。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;MSN Messenger 协议&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;MSN Messenger Network是微软提供的即时通讯会话网，成立于1999年。和它同期即时通讯软件有AOL Instant Messenger，ICQ及Yahoo Messenger等，是老牌IM软件了。虽然国内基本上是腾讯的天下，但MSN还是半死不活的占着一席之地的。和X讯不同的是，MSN的协议是公开的，也就是说，我们可以自己实现一个MSN客户端。MSN Messenger协议是学习网络编程的一个比较好的材料的。&lt;/p&gt;&lt;p&gt;MSN协议是在不断修改演进的，但基本上仍然是保持着向下兼容的，本文主要是参考&lt;a href="http://www.hypothetic.org/docs/msn/index.php网站上列举的MSN8"&gt;http://www.hypothetic.org/docs/msn/index.php网站上列举的MSN8&lt;/a&gt;协议来的，虽然非常老了，但实现其基本功能还是没有问题的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;基础知识&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;所有的到MSN服务器连接都是建立在TCP/IP之上的。一般采用1863作为通信端口（其通信服务器可能会由分派服务器重定向，重定向后的端口不一定是1863）。&lt;/p&gt;&lt;p&gt;MSN协议大体上还是基于字符串的，其送和接收的编码为UTF-8编码。另外，由于字符串协议通常采用了空格等作为协议字段的分隔符，因此，使用了空格的昵称，显示名，组名，电话号码等一些地方需要采用URL编码方式转换依次（这些和具体的命令相关，是规定好了的）。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;MSN消息格式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;MSN之间的应答方式一般称为命令，一个基本的MSN应答消息格式如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="background-color: yellow;"&gt;VER&lt;/span&gt;&lt;span style="background-color: lime;"&gt;15&lt;/span&gt;&lt;span style="background-color: lightgrey;"&gt;MSNP8 FOO CVR0 BAR&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;br /&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;lt;&amp;lt;&amp;lt; VER 15 MSNP8 CVR0&lt;span style="color: rgb(204, 204, 204);"&gt;\r\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: rgb(51, 51, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;从上看出，一条MSN命令基本包括如下三个部分，&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;首三个字符标识命令类型。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;随后的一个数字为事务ID，主要用来用于应答方式的交互，通过事务ID来匹配请求和响应命令。（对于那些不需要应答的命令，事务ID不是必须的）&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;再随后一直到行尾都是命令的参数，参数间通过空格来分割。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;最后的&lt;/span&gt;&lt;span style="color: rgb(204, 204, 204); font-family: Consolas; font-size: 12pt;"&gt;&lt;strong&gt;\r\n&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-size: 10pt;"&gt;就是命令行标识符了。但需要注意的是，对于四条特殊的命令QRY、PAG、NOT及MSG，它们是可以超过一行的，这些命令（QRY和MSG是这样的，其余的两个暂时还没有用到）的最后一个参数标明了剩余字符的字节数（不是字符长度）。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 170); font-family: Consolas; font-size: 9pt;"&gt;&lt;span style="background-color: white;"&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; QRY 1049 msmsgs@msnmsgr.com 32&lt;span style="color: rgb(204, 204, 204);"&gt;/r/n&lt;span style="color: rgb(0, 0, 170);"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8f2f5a91b72102cd28355e9fc9000d6e&amp;nbsp;&lt;span style="color: rgb(0, 170, 170);"&gt;(no newline)&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;根据命令格式的语法，则可以大致定义出解析的算法：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;首先读一行，解析出命令类型，事务ID，参数等信息&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;如果命令为MSG等超过一行的格式，根据参数中剩余消息长度来读取剩余消息。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;命令次序&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;MSN命令基本上是一个异步响应的过程，它非常不好解析，主要原因如下：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;通常情况下，应答命令会以它们被发送的次序发送。但并不总是这样，有时你可能以1，2，3的次序发送命令，而服务器以2，3，1的次序响应，此时就需要靠事务ID来匹配请求和应答了。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;有些命令（如CHG等）会得到服务器的多个应答。这些应答中包含相同的事务ID和原始命令。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;另外，它还和没有固定的顺序和时机的通知消息复用了同一个TCP流，解析起来还是十分令人头疼的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;惩罚策略&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;由于程序不可能一口气完美实现，有时我们可能无意间对MSN服务器进行一些不遵循协议要求的操作（当然，也不排除有人在好心测试MSN服务器的防攻击能力），如发送的不遵循协议格式的消息，对服务器的应答没有正确回复等。&lt;/p&gt;&lt;p&gt;对于这些非法操作，MSN服务器一般会断掉当前连接，有时还会在一定时间内不响应该地址的请求（一般十分钟左右就解封了）。另外，对于服务器的命令不合法回复（或不回复）时，服务器可能在一定时间内不会再次通知该事件，就算重新登录也一样（一般也是十分钟左右就解封了），在开发过程中尤其需要注意一下。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;MSN Message对象的实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;首先附上MSN消息的C#实现：&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('190e62a3-c1b9-4a58-9cb8-d19718a1ef9c')"&gt;&lt;img style="display: none;" id="code_img_opened_190e62a3-c1b9-4a58-9cb8-d19718a1ef9c" class="code_img_opened" onclick="cnblogs_code_hide('190e62a3-c1b9-4a58-9cb8-d19718a1ef9c',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_190e62a3-c1b9-4a58-9cb8-d19718a1ef9c" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;abstract&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;MsnPacket&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;?&amp;nbsp;TransactionId&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;CmdType&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;[]&amp;nbsp;Paras&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;virtual&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt;&amp;nbsp;WaitReply&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;TransactionId&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;;&amp;nbsp;}&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;virtual&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;ExtraMessage&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;;&amp;nbsp;}&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;MsnPacket(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;cmdType,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;?&amp;nbsp;transId,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;[]&amp;nbsp;paras)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Requires((cmdType&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(paras&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.CmdType&amp;nbsp;=&amp;nbsp;cmdType;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.TransactionId&amp;nbsp;=&amp;nbsp;transId;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.Paras&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.Join(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;paras.Select(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.Trim())).Split(&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;防止有的参数中带空格&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;ToString()&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(!&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.IsNullOrEmpty(ExtraMessage))&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Assume((CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;MSG&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&amp;nbsp;||&amp;nbsp;(CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;QRY&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&amp;nbsp;||&amp;nbsp;(CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;PAG&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;)&amp;nbsp;||&amp;nbsp;(CmdType&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;NOT&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;contentSize&amp;nbsp;=&amp;nbsp;Encoding.UTF8.GetByteCount(ExtraMessage);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Paras[Paras.Length&amp;nbsp;-&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;contentSize.ToString();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Assume(contentSize&amp;nbsp;&amp;lt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;1664&lt;/span&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;TODO&amp;nbsp;如果消息长度超过1664，需要拆分发送，目前不支持这种超长消息的发送&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.Format(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;{0}&amp;nbsp;{1}{2}\r\n{3}&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CmdType,&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TransactionId&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;&amp;nbsp;?&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;""&lt;/span&gt;&amp;nbsp;:&amp;nbsp;TransactionId&amp;nbsp;+&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.Join(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;Paras),&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExtraMessage);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;Regex&amp;nbsp;regexp&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Regex(&lt;span style="color: rgb(128, 0, 0);"&gt;@"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;^(?&amp;lt;cmd&amp;gt;\w{3})(?&amp;lt;id&amp;gt;&amp;nbsp;\d+){0,1}(?&amp;lt;para&amp;gt;&amp;nbsp;.+){0,1}&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;MsnPacket&amp;gt;&amp;nbsp;ReadAsync(System.IO.StreamReader&amp;nbsp;reader)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Requires(reader&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;info&amp;nbsp;=&amp;nbsp;await&amp;nbsp;reader.ReadLineAsync();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CheckReadResult(info&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;groups&amp;nbsp;=&amp;nbsp;regexp.Match(info).Groups;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;cmdType&amp;nbsp;=&amp;nbsp;groups[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;cmd&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;].Value;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;actionID&amp;nbsp;=&amp;nbsp;groups[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;id&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;].Success&amp;nbsp;?&amp;nbsp;(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;?)&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;.Parse(groups[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;id&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;].Value.Trim())&amp;nbsp;:&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;paras&amp;nbsp;=&amp;nbsp;groups[&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;para&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;].Value.Trim().Split(&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(cmdType&amp;nbsp;!=&amp;nbsp;MsnMessage.CommandType)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;其它三种超过一行的命令QRY，PAG，NOT不是应答命令，这里碰不到&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;MsnCommand(cmdType,&amp;nbsp;actionID,&amp;nbsp;paras);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;contentSize&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;.Parse(paras.Last());&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;extraMsg&amp;nbsp;=&amp;nbsp;await&amp;nbsp;ReadBlockAsync(reader,&amp;nbsp;contentSize);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;headers&amp;nbsp;=&amp;nbsp;MsnMessage.ParseHeaders(extraMsg);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;content&amp;nbsp;=&amp;nbsp;Regex.Match(extraMsg,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;@"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;.*?\r\n\r\n(.*)&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;RegexOptions.Singleline).Groups[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;].Value;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;MsnMessage(actionID,&amp;nbsp;paras,&amp;nbsp;headers,&amp;nbsp;content);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;catch&lt;/span&gt;&amp;nbsp;(FormatException)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;68&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;69&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;ReadBlockAsync(System.IO.StreamReader&amp;nbsp;reader,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;&amp;nbsp;bytesCount)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;70&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;71&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Requires((reader&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(bytesCount&amp;nbsp;&amp;gt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;72&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;73&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;currentCount&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;74&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;content&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;StringBuilder();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;75&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;chBuffer&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;char&lt;/span&gt;[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;76&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;77&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;while&lt;/span&gt;&amp;nbsp;(currentCount&amp;nbsp;&amp;lt;&amp;nbsp;bytesCount)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;78&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;79&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;writeCount&amp;nbsp;=&amp;nbsp;await&amp;nbsp;reader.ReadBlockAsync(chBuffer,&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;80&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CheckReadResult(writeCount&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;81&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;82&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;content.Append(chBuffer[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;]);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;83&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currentCount&amp;nbsp;+=&amp;nbsp;reader.CurrentEncoding.GetByteCount(chBuffer);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;84&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;85&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;86&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Assume(currentCount&amp;nbsp;==&amp;nbsp;bytesCount);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;87&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;content.ToString();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;88&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;89&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;90&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&amp;nbsp;CheckReadResult(&lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt;&amp;nbsp;isSuccess)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;91&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;92&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(isSuccess)&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;93&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;FormatException();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;94&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;95&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;96&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;97&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;98&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;MsnCommand&amp;nbsp;:&amp;nbsp;MsnPacket&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;99&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;100&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;Content&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;101&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;102&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;MsnCommand(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;cmdType,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;?&amp;nbsp;transId,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;params&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;[]&amp;nbsp;paras)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;103&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;base&lt;/span&gt;(cmdType,&amp;nbsp;transId,&amp;nbsp;paras)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;104&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;105&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;106&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;107&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;ExtraMessage&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;Content;&amp;nbsp;}&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;108&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;109&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;110&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;MsnMessage&amp;nbsp;:&amp;nbsp;MsnPacket&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;111&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;112&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;Headers&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;113&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;Content&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;114&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt;&amp;nbsp;WaitReply&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;false&lt;/span&gt;;&amp;nbsp;}&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;115&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;const&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;CommandType&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;MSG&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;116&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;117&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;MsnMessage(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;?&amp;nbsp;transId,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;[]&amp;nbsp;paras,Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;headers,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;content)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;118&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;base&lt;/span&gt;(CommandType,&amp;nbsp;transId,&amp;nbsp;paras)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;119&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;120&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.Headers&amp;nbsp;=&amp;nbsp;headers;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;121&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.Content&amp;nbsp;=&amp;nbsp;content;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;122&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;123&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;124&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;MsnMessage(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;&amp;nbsp;transId,&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;headers,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;content)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;125&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;(transId,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;[]&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;N&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;},&amp;nbsp;headers,&amp;nbsp;content)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;126&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;127&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;/*&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;本来有U(不确认)、A（都确认）、N（发送失败时确认）三种类型的。&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;128&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;这里为了简单，直接选择的是N，但不收应答消息(Message.WaitReply&amp;nbsp;=&amp;nbsp;false)，发送失败作为通知响应&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;129&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;130&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;131&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;ExtraMessage&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;132&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;133&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;134&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;135&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;headerMsg&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;.Join(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;\r\n&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;Headers.Select(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.Key&amp;nbsp;+&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;i.Value));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;136&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;headerMsg&amp;nbsp;+&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;\r\n\r\n&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;Content;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;137&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;138&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;139&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;140&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;internal&lt;/span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;ParseHeaders(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;extraMsg)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;141&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;142&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;headers&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;143&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;match&amp;nbsp;=&amp;nbsp;Regex.Match(extraMsg,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;@"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;(.*?)\r\n\r\n&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;,&amp;nbsp;RegexOptions.Singleline);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;144&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;headerMsg&amp;nbsp;=&amp;nbsp;match.Groups[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;].Value;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;145&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;foreach&lt;/span&gt;&amp;nbsp;(Match&amp;nbsp;item&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;in&lt;/span&gt;&amp;nbsp;Regex.Matches(headerMsg,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;@"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;(.+?):&amp;nbsp;(.+)&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;))&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;146&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;147&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;key&amp;nbsp;=&amp;nbsp;item.Groups[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;].Value;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;148&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;value&amp;nbsp;=&amp;nbsp;item.Groups[&lt;span style="color: rgb(128, 0, 128);"&gt;2&lt;/span&gt;].Value.Trim();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;149&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;headers[key]&amp;nbsp;=&amp;nbsp;value;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;150&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;151&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;headers;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;152&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;153&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;代码非常简单，只有三个类；其中MsnPacket是虚基类，其它两个MsnCommand和MsnMessage是子类。本来三个类可以统一用一个MsnCommand来表示的，但由于MSG类型的消息相对较为复杂和常用，需要单独构造和解析其消息头。因此单独用一个MsnMessage类来表示。&lt;/p&gt;&lt;p&gt;当我们连上MSN服务器时，就可以通过MsnPacket.ReadAsync()函数来读取并解析出MSN消息对象了，具体方法参看下面的MsnServer的实现。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;MSN Server对象的实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在MSN消息里，发送命令和接收应答是一个同步模型，而服务器通知又是一个异步模型，本来很不好处理。但通过C#的TAP和RX两种异步解决方案还是可以很优雅的实现它的解析，方式如下：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;发送命令行后，通过TaskCompletionSource对象异步等待服务器通知应答结果&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;异步接收消息，如果是发送命令的应答则通过等待的TaskCompletionSource对象返回结果，如果是服务器通知则通过Iobservable的数据源分发。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('5dca6da4-990a-46db-80c6-57ad20699a29')"&gt;&lt;img style="display: none;" id="code_img_opened_5dca6da4-990a-46db-80c6-57ad20699a29" class="code_img_opened" onclick="cnblogs_code_hide('5dca6da4-990a-46db-80c6-57ad20699a29',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_5dca6da4-990a-46db-80c6-57ad20699a29" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&amp;nbsp;MsnServer&amp;nbsp;:&amp;nbsp;IDisposable&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StreamWriter&amp;nbsp;writer;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Subject&amp;lt;MsnCommand&amp;gt;&amp;nbsp;notifyCmds&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Subject&amp;lt;MsnCommand&amp;gt;();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Subject&amp;lt;MsnMessage&amp;gt;&amp;nbsp;notifyMsgs&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Subject&amp;lt;MsnMessage&amp;gt;();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;MsnCommand&amp;gt;&amp;nbsp;NotifyCmds&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;notifyCmds;&amp;nbsp;}&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;MsnMessage&amp;gt;&amp;nbsp;NotifyMsgs&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;notifyMsgs;&amp;nbsp;}&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;MsnServer(Stream&amp;nbsp;stream)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.writer&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;StreamWriter(stream,&amp;nbsp;Encoding.UTF8);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.IsConnected&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RecevieAsync(&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;StreamReader(stream,&amp;nbsp;Encoding.UTF8));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;TODO&amp;nbsp;这儿最好还需要加一个老化处理，删除长期没有应答的命令&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;,&amp;nbsp;TaskCompletionSource&amp;lt;MsnCommand&amp;gt;&amp;gt;&amp;nbsp;replyList&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;,&amp;nbsp;TaskCompletionSource&amp;lt;MsnCommand&amp;gt;&amp;gt;();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;MsnCommand&amp;gt;&amp;nbsp;SendAsync(MsnPacket&amp;nbsp;cmd)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Contract.Requires(cmd&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(!cmd.WaitReply)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;不需要等待应答&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;SendAsync(cmd.ToString());&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;replySource&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;TaskCompletionSource&amp;lt;MsnCommand&amp;gt;();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;replyList[(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;)cmd.TransactionId]&amp;nbsp;=&amp;nbsp;replySource;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;SendAsync(cmd.ToString());&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(await&amp;nbsp;Task.WhenAny(replySource.Task,&amp;nbsp;Task.Delay(&lt;span style="color: rgb(128, 0, 128);"&gt;15000&lt;/span&gt;))&amp;nbsp;!=&amp;nbsp;replySource.Task)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;errMsg&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;接收应答超时:&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;cmd;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.Red,&amp;nbsp;errMsg);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.Dispose();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;replySource.SetException(&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;TimeoutException(errMsg));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;TimeoutException(errMsg);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;replySource.Task.Result;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&amp;nbsp;RecevieAsync(StreamReader&amp;nbsp;reader)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(!IsConnected)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;packet&amp;nbsp;=&amp;nbsp;await&amp;nbsp;MsnPacket.ReadAsync(reader);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(packet&amp;nbsp;==&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.WriteLine(ConsoleColor.Red,&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;连接中断&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dispose();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.Write(ConsoleColor.Yellow,&amp;nbsp;packet);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;replySource&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt;&amp;nbsp;TaskCompletionSource&amp;lt;MsnCommand&amp;gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;((packet.TransactionId&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(replyList.TryGetValue((&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;)packet.TransactionId,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;out&lt;/span&gt;&amp;nbsp;replySource)))&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;replySource.SetResult(packet&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt;&amp;nbsp;MsnCommand);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;68&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;replyList.Remove((&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;)packet.TransactionId);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;69&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;70&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;71&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;72&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(packet&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;is&lt;/span&gt;&amp;nbsp;MsnMessage)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;73&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyMsgs.OnNext(packet&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt;&amp;nbsp;MsnMessage);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;74&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;75&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyCmds.OnNext(packet&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt;&amp;nbsp;MsnCommand);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;76&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;77&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;78&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;finally&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;79&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;80&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RecevieAsync(reader);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;81&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;82&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;83&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;84&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;Task&amp;lt;MsnCommand&amp;gt;&amp;nbsp;SendAsync(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;cmdType,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;params&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt;[]&amp;nbsp;paras)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;85&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;86&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;cmd&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;MsnCommand(cmdType,&amp;nbsp;NewTransactionId(),&amp;nbsp;paras.Select(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.ToString()).ToArray());&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;87&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;SendAsync(cmd);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;88&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;89&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;90&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;Task&amp;nbsp;SendAsync(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;info)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;91&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;92&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;await&amp;nbsp;writer.WriteAsync(info);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;不知道为什么这么写发不出去&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;93&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;await&amp;nbsp;writer.FlushAsync();&lt;/span&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;94&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 128, 0);"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;95&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;data&amp;nbsp;=&amp;nbsp;writer.Encoding.GetBytes(info);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;96&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;writer.BaseStream.WriteAsync(data,&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;,&amp;nbsp;data.Length);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;97&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;writer.BaseStream.FlushAsync();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;98&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;99&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.Write(ConsoleColor.Gray,&amp;nbsp;info);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;100&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;101&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;102&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;nbsp;SendPing()&amp;nbsp;{&amp;nbsp;await&amp;nbsp;SendAsync(&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;PNG\r\n&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;103&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;IObservable&amp;lt;MsnCommand&amp;gt;&amp;nbsp;ReceiveUntilPingBack()&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;notifyCmds.TakeWhile(i&amp;nbsp;=&amp;gt;&amp;nbsp;i.CmdType&amp;nbsp;!=&amp;nbsp;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;QNG&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;"&lt;/span&gt;);&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;104&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;105&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;#region&lt;/span&gt;&amp;nbsp;IDisposable&amp;nbsp;成员&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;106&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;107&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt;&amp;nbsp;IsConnected&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;108&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&amp;nbsp;Close()&amp;nbsp;{&amp;nbsp;Dispose();&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;109&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&amp;nbsp;Dispose()&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;110&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;111&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&amp;nbsp;(!IsConnected)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;112&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;113&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;114&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IsConnected&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;115&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writer.Dispose();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;116&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyCmds.OnCompleted();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;117&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;notifyMsgs.OnCompleted();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;118&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;119&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;120&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;121&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;122&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;Task&amp;lt;MsnServer&amp;gt;&amp;nbsp;CreateAsync(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;hostAndPort)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;123&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;124&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;epData&amp;nbsp;=&amp;nbsp;hostAndPort.Split(&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;'&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;125&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;CreateAsync(epData[&lt;span style="color: rgb(128, 0, 128);"&gt;0&lt;/span&gt;],&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;.Parse(epData[&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;]));&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;126&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;127&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;128&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;async&amp;nbsp;Task&amp;lt;MsnServer&amp;gt;&amp;nbsp;CreateAsync(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;nbsp;host,&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;&amp;nbsp;port)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;129&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;130&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;var&lt;/span&gt;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;System.Net.Sockets.TcpClient();&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;131&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;client.ConnectAsync(host,&amp;nbsp;port);&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;132&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;133&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;&amp;nbsp;MsnServer(client.GetStream());&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;134&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;135&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;136&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;&amp;nbsp;curTransId&amp;nbsp;=&amp;nbsp;&lt;span style="color: rgb(128, 0, 128);"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;137&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt;&amp;nbsp;NewTransactionId()&amp;nbsp;{&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&amp;nbsp;curTransId++;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;138&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;139&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;服务器端的实现也不复杂，只有一百行左右代码。它其实就是一个Socket的封装，可以通过构造函数或MsnServer.CreateAsync()异步创建。创建后，通过RecevieAsync()函数异步读取并解析Msn消息并分发。外部对象通过调用SendAsync()发送命令，并异步接收应答。&lt;/p&gt;&lt;p&gt;另外，我这里把MSG类型区分开了单独作为了一个数据源，主要是为了方便后面处理。其它的就不用多介绍了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;后记&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;由于时间有限，目前只介绍了关于MSN消息的格式及解析部分。下周估计会写篇文章介绍如何实现登陆，具体到收发消息的部分估计只能等到五一后了。主要参考资料可以见我以前的一篇文章--&lt;a href="http://www.cnblogs.com/TianFang/archive/2011/02/09/1950099.html"&gt;《MSN开发相关资料》&lt;/a&gt;。&lt;/p&gt;           &lt;img src="http://www.cnblogs.com/TianFang/aggbug/2460777.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/04/20/2460777.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/04/02/2429954.html</id><title type="text">HTML5中的WebSocket</title><summary type="text">背景在传统方式下，很多网站为了实现即时通讯，所用的技术都是轮询。轮询是在特定的的时间间隔（如每1秒），由浏览器对伺服器发出HTTP request，然后由伺服器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点，即浏览器需要不断的向伺服器发出请求，然而HTTP request 的header是非常长的，里面包含的数据可能只是一个很小的值，这样会占用很多的带宽和服务器资源。而比较新的技术去做轮询的效果是Comet，使用了AJAX。但这种技术虽然可达到双向通信，但依然需要发出请求，而且在Comet中，普遍采用了长链接，这也会大量消耗服务器带宽和资源。面对这种状况，HTML5定义了We</summary><published>2012-04-02T07:15:00Z</published><updated>2012-04-02T07:15:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/04/02/2429954.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/04/02/2429954.html"/><content type="html">&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在传统方式下，&lt;span style="font-size: 10pt;"&gt;很多网站为了实现即时通讯，所用的技术都是&lt;/span&gt;轮询&lt;span style="font-size: 10pt;"&gt;。轮询是在特定的的时间间隔（如每1秒），由浏览器对伺服器发出HTTP request，然后由伺服器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点，即浏览器需要不断的向伺服器发出请求，然而HTTP request 的header是非常长的，里面包含的数据可能只是一个很小的值，这样会占用很多的带宽和服务器资源。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;而比较新的技术去做轮询的效果是&lt;a title="Comet (web技术)" href="http://zh.wikipedia.org/wiki/Comet_(web%E6%8A%80%E6%9C%AF)"&gt;Comet&lt;/a&gt;，使用了AJAX。但这种技术虽然可达到双向通信，但依然需要发出请求，而且在Comet中，普遍采用了&lt;a title="HTTP持久链接" href="http://zh.wikipedia.org/wiki/HTTP%E6%8C%81%E4%B9%85%E9%93%BE%E6%8E%A5"&gt;长链接&lt;/a&gt;，这也会大量消耗服务器带宽和资源。&lt;/p&gt;&lt;p&gt;面对这种状况，&lt;a title="HTML5" href="http://zh.wikipedia.org/wiki/HTML5"&gt;HTML5&lt;/a&gt;定义了WebSocket协议，能更好的节省服务器资源和带宽并达到实时通讯。WebSocket 是HTML5一种新的协议。它是实现了浏览器与伺服器的双向通讯。&lt;/p&gt;&lt;p&gt;简单的讲，通过WebSocket，可以在浏览器和服务器间建立一个TCP长连接，服务器可以实现主动推送数据至客户端。目前为止，Chrome和Safari的最新版本浏览器已经支持WebSockets了（win8测试版中的IE10也是支持的）。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;客户端&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在支持WebSocket的浏览器中，可以直接在Javascript中通过WebSocket对象来实现通信。WebSocket对象主要通过onopen，onmessage，onclose即onerror四个事件实现对socket消息的异步响应。一个简单的示例如下：&lt;/p&gt;&lt;p&gt;&lt;span style="color: blue;"&gt;&lt;span style="font-family: Consolas; font-size: 9pt; background-color: white;"&gt;&amp;nbsp; &amp;nbsp; var&lt;span style="color: black;"&gt; socket = &lt;span style="color: blue;"&gt;new&lt;span style="color: black;"&gt; WebSocket(&lt;span style="color: maroon;"&gt;"ws://localhost:8080/"&lt;span style="color: black;"&gt;);&lt;br /&gt;&amp;nbsp; &amp;nbsp; socket.onopen = &lt;span style="color: blue;"&gt;function&lt;span style="color: black;"&gt; () {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; alert(&lt;span style="color: maroon;"&gt;"Socket has been opened!"&lt;span style="color: black;"&gt;);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; socket.onmessage = &lt;span style="color: blue;"&gt;function&lt;span style="color: black;"&gt; (msg) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; alert(msg); &lt;span style="color: green;"&gt;//Awesome!&lt;span style="color: black;"&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/tianfang/websocket.jpg" width="500" height="250" /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;关于其详细信息可以查看W3网站上的&lt;a href="http://dev.w3.org/html5/websockets/"&gt;WebSocket API&lt;/a&gt;&lt;/p&gt;&lt;p&gt;这里附一个网上找的简单的聊天页面的实现：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('5ef81b1c-e116-4218-bf17-97d970f10fd8')"&gt;&lt;img style="display: none;" id="code_img_opened_5ef81b1c-e116-4218-bf17-97d970f10fd8" class="code_img_opened" onclick="cnblogs_code_hide('5ef81b1c-e116-4218-bf17-97d970f10fd8',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;div id="cnblogs_code_open_5ef81b1c-e116-4218-bf17-97d970f10fd8" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;html&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;head&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;title&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;WebSocket&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;title&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;style&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;html,&amp;nbsp;body&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;{&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;normal&amp;nbsp;0.9em&amp;nbsp;arial,helvetica&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;}&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#log&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;{&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;440px&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;200px&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;#7F9DB9&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;13&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;auto&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;}&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#msg&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;{&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;330px&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;18&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(255, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;}&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;19&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(128, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;style&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;script&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;21&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;var&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;socket;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;22&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;23&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;init()&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;24&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;var&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;host&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;ws://localhost:8080/&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;25&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;try&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;26&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;new&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;WebSocket(host);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;27&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket.onopen&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(msg)&amp;nbsp;{;&amp;nbsp;};&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;28&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket.onmessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(msg)&amp;nbsp;{&amp;nbsp;log(msg.data);&amp;nbsp;};&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;29&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket.onclose&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(msg)&amp;nbsp;{&amp;nbsp;log(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;connection&amp;nbsp;closed.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;);&amp;nbsp;};&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;30&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;31&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;catch&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(ex)&amp;nbsp;{&amp;nbsp;log(ex);&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;32&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;msg&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;).focus();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;33&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;34&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;35&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;send()&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;36&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;var&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;txt,&amp;nbsp;msg;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;37&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;txt&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;$(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;msg&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;38&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;txt.value;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;39&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;if&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;!&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;msg)&amp;nbsp;{&amp;nbsp;alert(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;Message&amp;nbsp;can&amp;nbsp;not&amp;nbsp;be&amp;nbsp;empty&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;);&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;return&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;40&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;txt.value&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;""&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;41&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;txt.focus();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;42&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;try&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;{&amp;nbsp;socket.send(msg);&amp;nbsp;}&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;catch&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(ex)&amp;nbsp;{&amp;nbsp;log(ex);&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;43&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;44&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;45&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.onbeforeunload&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;()&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;46&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;try&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;47&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket.send(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;quit&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;48&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket.close();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;49&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;socket&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;null&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;50&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;51&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;catch&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(ex)&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;52&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;log(ex);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;53&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;54&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;55&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;56&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;57&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;$(id)&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;return&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;document.getElementById(id);&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;58&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;log(msg)&amp;nbsp;{&amp;nbsp;$(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;log&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;).innerHTML&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;+=&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;+&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;msg;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;59&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;function&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;onkey(event)&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255); background-color: rgb(245, 245, 245);"&gt;if&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;(event.keyCode&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;==&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;13&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;)&amp;nbsp;{&amp;nbsp;send();&amp;nbsp;}&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;60&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;script&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;61&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;head&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;62&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;body&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;onload&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;="init()"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;63&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;h3&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;WebSocket&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;h3&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;64&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;br&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;65&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;br&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;div&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;id&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;="log"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;div&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;67&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;input&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;id&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;="msg"&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&amp;nbsp;type&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;="textbox"&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&amp;nbsp;onkeypress&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;="onkey(event)"&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;68&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;button&amp;nbsp;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;onclick&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;="send()"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;Send&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;button&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;69&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;body&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 128);"&gt;70&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;html&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;服务器端&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在.Net 4.5中，在System.Web.WebSockets和System.Net.WebSocket名字空间实现了对WebSocket的支持，其中前者主要用于Asp.net框架。如下是一个简单的EchoServer的实现。&lt;/p&gt;&lt;p&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Consolas; font-size: 9pt; background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;class&lt;span style="color: black;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;WebSocketServer&lt;span style="color: black;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;span style="color: black;"&gt; WebSocketServer()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Start();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;async&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;void&lt;span style="color: black;"&gt; Start()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; listener = &lt;span style="color: blue;"&gt;new&lt;span style="color: black;"&gt; HttpListener();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;listener.Prefixes.Add(&lt;span style="color: maroon;"&gt;"http://localhost:8080/"&lt;span style="color: black;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;listener.Start();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;while&lt;span style="color: black;"&gt; (&lt;span style="color: blue;"&gt;true&lt;span style="color: black;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; context = &lt;span style="color: blue;"&gt;await&lt;span style="color: black;"&gt; listener.GetContextAsync();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(43, 145, 175);"&gt;Console&lt;span style="color: black;"&gt;.WriteLine(&lt;span style="color: maroon;"&gt;"connected"&lt;span style="color: black;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; websocketContext = &lt;span style="color: blue;"&gt;await&lt;span style="color: black;"&gt; context.AcceptWebSocketAsync(&lt;span style="color: blue;"&gt;null&lt;span style="color: black;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProcessClient(websocketContext.WebSocket);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;async&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;void&lt;span style="color: black;"&gt; ProcessClient(WebSocket websocket)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; data = &lt;span style="color: blue;"&gt;new&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;byte&lt;span style="color: black;"&gt;[1500];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; buffer = &lt;span style="color: blue;"&gt;new&lt;span style="color: black;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ArraySegment&lt;span style="color: black;"&gt;&amp;lt;&lt;span style="color: blue;"&gt;byte&lt;span style="color: black;"&gt;&amp;gt;(data);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;while&lt;span style="color: black;"&gt; (&lt;span style="color: blue;"&gt;true&lt;span style="color: black;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; result = &lt;span style="color: blue;"&gt;await&lt;span style="color: black;"&gt; websocket.ReceiveAsync(buffer, &lt;span style="color: rgb(43, 145, 175);"&gt;CancellationToken&lt;span style="color: black;"&gt;.None);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;span style="color: black;"&gt; (result.CloseStatus != &lt;span style="color: blue;"&gt;null&lt;span style="color: black;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(43, 145, 175);"&gt;Console&lt;span style="color: black;"&gt;.WriteLine(&lt;span style="color: maroon;"&gt;"socket closed"&lt;span style="color: black;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;websocket.Abort();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;span style="color: black;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(43, 145, 175);"&gt;Console&lt;span style="color: black;"&gt;.WriteLine(&lt;span style="color: maroon;"&gt;"&amp;gt;&amp;gt;&amp;gt; "&lt;span style="color: black;"&gt; + &lt;span style="color: rgb(43, 145, 175);"&gt;Encoding&lt;span style="color: black;"&gt;.UTF8.GetString(data, 0, result.Count));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;await&lt;span style="color: black;"&gt; websocket.SendAsync(buffer, WebSocketMessageType.Text, &lt;span style="color: blue;"&gt;true&lt;span style="color: black;"&gt;, &lt;span style="color: rgb(43, 145, 175);"&gt;CancellationToken&lt;span style="color: black;"&gt;.None);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;得益于C#的async特性，实现WebSocket服务器是非常简洁的，不过我没有找到实现客户端的方法，如果谁知道望指点一下。但令人不解的是这个api只支持win8（虽然从MSDN上来看是支持win7等其它系统的），不知道最后正式版会不会去掉这个操作系统的限制。&lt;/p&gt;&lt;p&gt;要在非win8环境下实现WebSocket，可以试一下&lt;a href="http://superwebsocket.codeplex.com/"&gt;SuperWebSocket&lt;/a&gt;（服务器端）和&lt;a href="http://websocket4net.codeplex.com/"&gt;WebSocket4Net&lt;/a&gt;（客户端）这两个开源库。当然，非.net的实现也是非常多的，常见的就有&lt;a href="http://code.google.com/p/phpwebsockets/" target="_blank"&gt;phpwebsockets&lt;/a&gt;，&lt;a href="http://jwebsocket.org/" target="_blank"&gt;jWebSocket&lt;/a&gt;，&lt;a href="http://github.com/gimite/web-socket-ruby" target="_blank"&gt;web-socket-ruby&lt;/a&gt;等，这里就不一一列举了。&lt;/p&gt;&lt;p&gt;由于现在这段时间较忙，对于WebSocket也只是处于概念性的学习，浅尝辄止。如果有时间的话后续再写一下关于WebSocket协议和实现的相关文章。&lt;/p&gt;     &lt;img src="http://www.cnblogs.com/TianFang/aggbug/2429954.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/04/02/2429954.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/03/18/2404659.html</id><title type="text">WPF中判断是否处于设计模式</title><summary type="text">在WPF中，有时需要判断当前是否处于设计模式，以屏蔽设计器执行构造函数里面的部分功能public static bool IsInDesignMode(this Control control){return System.ComponentModel.DesignerProperties.GetIsInDesignMode(control);}</summary><published>2012-03-18T06:45:00Z</published><updated>2012-03-18T06:45:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/03/18/2404659.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/03/18/2404659.html"/><content type="html">&lt;p&gt;在WPF中，有时需要判断当前是否处于设计模式，以屏蔽设计器执行构造函数里面的部分功能&lt;/p&gt;&lt;p&gt;&lt;span style="color: black; font-family: Consolas; font-size: 9pt; background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;static&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;bool&lt;span style="color: black;"&gt; IsInDesignMode(&lt;span style="color: blue;"&gt;this&lt;span style="color: black;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Control&lt;span style="color: black;"&gt; control)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;span style="color: black;"&gt; System.ComponentModel.&lt;span style="color: rgb(43, 145, 175);"&gt;DesignerProperties&lt;span style="color: black;"&gt;.GetIsInDesignMode(control);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;img src="http://www.cnblogs.com/TianFang/aggbug/2404659.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/03/18/2404659.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/03/10/2389480.html</id><title type="text">.Net 4.5中的HttpClient试用</title><summary type="text">.Net 4.5中增加了一个新的System.Net.Http.HttpClient名字空间（在 System.Net.Http.dll 中），用于发送 HTTP 请求和接收 HTTP 响应。基本操作和以前的HttpWebRequest相比，HttpClient更加简洁，下面就是一个下载www.windows.com页面的示例：string uri = "http://www.window...</summary><published>2012-03-10T12:47:00Z</published><updated>2012-03-10T12:47:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/03/10/2389480.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/03/10/2389480.html"/><content type="html">&lt;p&gt;.Net 4.5中增加了一个新的System.Net.Http.HttpClient名字空间（在 System.Net.Http.dll 中），用于发送 HTTP 请求和接收 HTTP 响应。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;基本操作&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;和以前的HttpWebRequest相比，HttpClient更加简洁，下面就是一个下载&lt;span style="color:maroon; font-family:Consolas; font-size:9pt; background-color:white"&gt;www.windows.com&lt;/span&gt;页面的示例：&lt;/p&gt;&lt;p&gt;&lt;span style="color:black"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;    &lt;span style="color:blue"&gt;string&lt;span style="color:black"&gt; uri = &lt;span style="color:maroon"&gt;"http://www.windows.com/"&lt;span style="color:black"&gt;;&lt;br/&gt;    &lt;span style="color:#2b91af"&gt;HttpClient&lt;span style="color:black"&gt; client = &lt;span style="color:blue"&gt;new&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;HttpClient&lt;span style="color:black"&gt;();&lt;br/&gt;    &lt;span style="color:blue"&gt;string&lt;span style="color:black"&gt; body = &lt;span style="color:blue"&gt;await&lt;span style="color:black"&gt; client.GetStringAsync(uri);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;它支持编码识别和对压缩的http流解压，省去了我们的不少代码。除&lt;span style="color:black; font-family:Consolas; font-size:9pt; background-color:white"&gt;GetStringAsync()&lt;/span&gt;之外，还有&lt;span style="color:black; font-size:9pt"&gt;&lt;span style="font-family:Consolas; background-color:white"&gt;GetByteArrayAsync()&lt;/span&gt;&lt;span style="font-family:宋体"&gt;、&lt;/span&gt;&lt;span style="font-family:Consolas; background-color:white"&gt;GetStreamAsync()&lt;/span&gt;&lt;span style="font-family:宋体"&gt;、&lt;/span&gt;&lt;span style="font-family:Consolas; background-color:white"&gt;PostAsync ()&lt;/span&gt;&lt;span style="font-family:宋体"&gt;、&lt;/span&gt;&lt;span style="font-family:Consolas; background-color:white"&gt;DeleteAsync()&lt;/span&gt;&lt;/span&gt;等函数，非常好用。&lt;/p&gt;&lt;p&gt;&lt;span style="color:#2b91af"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClient&lt;span style="color:black"&gt;.GetStringAsync()&lt;/span&gt;&lt;/span&gt;是一个简化的函数，用这个函数的时候，我们看不到&lt;/span&gt;HttpResponse的相关信息，如果需要看到Http响应的信息，可以用如下标准方式：&lt;/p&gt;&lt;p&gt;&lt;span style="color:black"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;    &lt;span style="color:#2b91af"&gt;HttpResponseMessage&lt;span style="color:black"&gt; response = &lt;span style="color:blue"&gt;await&lt;span style="color:black"&gt; client.GetAsync(uri);&lt;br/&gt;    response.EnsureSuccessStatusCode();&lt;br/&gt;    &lt;span style="color:blue"&gt;string&lt;span style="color:black"&gt; responseBody = &lt;span style="color:blue"&gt;await&lt;span style="color:black"&gt; response.Content.ReadAsStringAsync();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;自定义HttpHeader&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;前面的示例非常简单，但有时我们需要在发送Get请求时在HttpHeader中加入一些额外的信息，常见的的有Refer、Cookie及UserAgent等。这个时候我们就要用到&lt;span style="color:#2b91af; font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClientHandler&lt;/span&gt;了，具体方法如下：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="text-align: justify"&gt;&lt;span style="font-size:10pt"&gt;首先自定义一个&lt;/span&gt;&lt;span style="color:#2b91af; font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClienHanlder&lt;/span&gt;&lt;span style="font-size:10pt"&gt;类，重载SendAsync方法。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="color:black"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;    &lt;span style="color:blue"&gt;string&lt;span style="color:black"&gt; uri = &lt;span style="color:maroon"&gt;"http://www.windows.com/"&lt;span style="color:black"&gt;;&lt;br/&gt;    &lt;span style="color:#2b91af"&gt;HttpClient&lt;span style="color:black"&gt; client = &lt;span style="color:blue"&gt;new&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;HttpClient&lt;span style="color:black"&gt;();&lt;br/&gt;&lt;br/&gt;    &lt;span style="color:blue"&gt;class&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;MyHttpClienHanlder&lt;span style="color:black"&gt;:&lt;span style="color:#2b91af"&gt;HttpClientHandler&lt;span style="color:black"&gt;&lt;br/&gt;    {&lt;br/&gt;        &lt;span style="color:blue"&gt;protected&lt;span style="color:black"&gt;&lt;span style="color:blue"&gt;override&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;Task&lt;span style="color:black"&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;HttpResponseMessage&lt;span style="color:black"&gt;&amp;gt; SendAsync(&lt;span style="color:#2b91af"&gt;HttpRequestMessage&lt;span style="color:black"&gt; request, &lt;span style="color:#2b91af"&gt;CancellationToken&lt;span style="color:black"&gt; cancellationToken)&lt;br/&gt;        {&lt;br/&gt;            request.Headers.Referrer = &lt;span style="color:blue"&gt;new&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;Uri&lt;span style="color:black"&gt;(&lt;span style="color:maroon"&gt;"http://www.google.com/"&lt;span style="color:black"&gt;);&lt;br/&gt;            request.Headers.Add(&lt;span style="color:maroon"&gt;"UserAgent"&lt;span style="color:black"&gt;, &lt;span style="color:maroon"&gt;"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727)"&lt;span style="color:black"&gt;);&lt;br/&gt;&lt;br/&gt;            &lt;span style="color:blue"&gt;return&lt;span style="color:black"&gt;&lt;span style="color:blue"&gt;base&lt;span style="color:black"&gt;.SendAsync(request, cancellationToken);&lt;br/&gt;        }&lt;br/&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="text-align: justify"&gt;&lt;span style="font-size:10pt"&gt;在&lt;/span&gt;&lt;span style="color:#2b91af; font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClient&lt;/span&gt;&lt;span style="font-size:10pt"&gt;构造函数中加入自定义的&lt;/span&gt;&lt;span style="color:#2b91af; font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClienHanlder&lt;/span&gt;&lt;span style="font-size:10pt"&gt;类。&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="color:black"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;    &lt;span style="color:blue"&gt;string&lt;span style="color:black"&gt; uri = &lt;span style="color:maroon"&gt;"http://www.windows.com/"&lt;span style="color:black"&gt;;&lt;br/&gt;    &lt;span style="color:#2b91af"&gt;HttpClient&lt;span style="color:black"&gt; client = &lt;span style="color:blue"&gt;new&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;HttpClient&lt;span style="color:black"&gt;(&lt;span style="color:blue"&gt;new&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;MyHttpClienHanlder&lt;span style="color:black"&gt;());&lt;br/&gt;    &lt;span style="color:blue"&gt;string&lt;span style="color:black"&gt; body = &lt;span style="color:blue"&gt;await&lt;span style="color:black"&gt; client.GetStringAsync(uri);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;可见，&lt;span style="color:#2b91af; font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClienHanlder&lt;/span&gt;其实就是是一个常见的代理模式的设计，它在&lt;span style="color:#2b91af"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClient&lt;span style="color:black"&gt;.GetStringAsync()&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt;中加了&lt;/span&gt;&lt;/span&gt;一层封装，拦截了HttpClient的输入和输出，从而实现一些自定义的操作。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;常见问题&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;HttpClient虽然非常简单易用，但并不意味着它任何时候都能照着我们期望的方式工作，常见问题（我这两天试用过程中遇到的）如下：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="text-align: justify"&gt;&lt;span style="font-size:10pt"&gt;中文乱码&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="color:#2b91af"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClient&lt;span style="color:black"&gt;.GetStringAsync()&lt;/span&gt;&lt;/span&gt;本身支持编码识别，但&lt;/span&gt;如果HttpResponse的HttpHeader中不含CharSet信息时，便采用默认编码方式进行字符串解码，它的默认编码方式是无法解析中文的，此时便会出现中文乱码。&lt;/p&gt;&lt;p&gt;一种常见的做法是：如果HttpHeader中不含CharSet信息时，采用GBK方式来解码。要实现这个功能的话，还是需要用到前面提到的&lt;span style="color:#2b91af; font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClientHandler&lt;/span&gt;。&lt;/p&gt;&lt;p&gt;&lt;span style="color:black"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;    &lt;span style="color:blue"&gt;class&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;MyHttpClienHanlder&lt;span style="color:black"&gt;:&lt;span style="color:#2b91af"&gt;HttpClientHandler&lt;span style="color:black"&gt;&lt;br/&gt;    {&lt;br/&gt;        &lt;span style="color:blue"&gt;protected&lt;span style="color:black"&gt;&lt;span style="color:blue"&gt;async&lt;span style="color:black"&gt;&lt;span style="color:blue"&gt;override&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;Task&lt;span style="color:black"&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;HttpResponseMessage&lt;span style="color:black"&gt;&amp;gt; SendAsync(&lt;span style="color:#2b91af"&gt;HttpRequestMessage&lt;span style="color:black"&gt; request, &lt;span style="color:#2b91af"&gt;CancellationToken&lt;span style="color:black"&gt; cancellationToken)&lt;br/&gt;        {&lt;br/&gt;            &lt;span style="color:blue"&gt;var&lt;span style="color:black"&gt; rsponse = &lt;span style="color:blue"&gt;await&lt;span style="color:black"&gt;&lt;span style="color:blue"&gt;base&lt;span style="color:black"&gt;.SendAsync(request, cancellationToken);&lt;br/&gt;            &lt;span style="color:blue"&gt;var&lt;span style="color:black"&gt; contentType = rsponse.Content.Headers.ContentType;&lt;br/&gt;            &lt;span style="color:blue"&gt;if&lt;span style="color:black"&gt; (&lt;span style="color:blue"&gt;string&lt;span style="color:black"&gt;.IsNullOrEmpty(contentType.CharSet))&lt;br/&gt;            {&lt;br/&gt;                contentType.CharSet = &lt;span style="color:maroon"&gt;"GBK"&lt;span style="color:black"&gt;;&lt;br/&gt;            }&lt;br/&gt;            &lt;span style="color:blue"&gt;return&lt;span style="color:black"&gt; rsponse;&lt;br/&gt;        }&lt;br/&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;当然，这么做仍然不是很完善，有的时候如果要更精确的话还需要从Html页面中获取charset信息，甚至通过相应的库函数进行编码猜测。具体实现的方法类似，这里就不一一细述了&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="text-align: justify"&gt;&lt;span style="font-size:10pt"&gt;响应内容过长导致HttpRequestException&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="color:#2b91af; font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClient&lt;/span&gt;有一个属性&lt;span style="color:black; font-family:Consolas; font-size:9pt; background-color:white"&gt;MaxResponseContentBufferSize&lt;/span&gt;，它表示的是读取响应内容时最大字节数缓冲区。它的默认值是64k，当页面内容很多，超过64k的时候，就会抛出一个HttpRequestException，导致Get失败。&lt;/p&gt;&lt;p&gt;这个属性必须是个正整数，也就是说，它是不支持自适应的，这个非常令人费解，不知道MS为什么非要自己估算页面大小，在Get操作前支持为合适的值，这个是个不够好用的地方。&lt;/p&gt;&lt;p&gt;我查了一下MSDN，目前对这个属性的说明比较少，不知道更改这个值的大小会影响什么地方。即使把他设置成int.Max貌似也不会有过多的内存占用。不过为了安全起见，还是把它设置在一个合理的范围吧，像我一般就把它设置为1m。&lt;/p&gt;&lt;p&gt;    &lt;span style="color:#2b91af"&gt;&lt;span style="font-family:Consolas; font-size:9pt; background-color:white"&gt;HttpClient&lt;span style="color:black"&gt; client = &lt;span style="color:blue"&gt;new&lt;span style="color:black"&gt;&lt;span style="color:#2b91af"&gt;HttpClient&lt;span style="color:black"&gt;() { MaxResponseContentBufferSize = 1024 * 1024 };&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;最后提一个不是问题的问题：HttpClient全部都是异步方法，没有同步方法，如果要在同步函数中使用，必须通过Task.Wait()来等待任务完成，稍稍有些不便。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TianFang/aggbug/2389480.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/03/10/2389480.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/03/06/2382830.html</id><title type="text">在C#中模拟大数乘法</title><summary type="text">今天见一道算法题，要求实现两个不限长度的正整数的乘法。感觉不难，便顺手做了一下。我这里的实现比较简单，基本上就是模拟算术运算，大概分成如下几步 125x11------- 125125--------1375将乘数每位与乘数相乘，获取到一个m*n的矩阵将矩阵错位相加，得到输出数组对输出中数组进行进位运算一个简单的实现如下static string Multiplication(string num1, string num2){var input1 = num1.Select(i =&gt; (int)(i - '0'));var input2 = num2.Select(i</summary><published>2012-03-06T15:58:00Z</published><updated>2012-03-06T15:58:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/03/06/2382830.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/03/06/2382830.html"/><content type="html">&lt;p&gt;今天见一道算法题，要求实现两个不限长度的正整数的乘法。感觉不难，便顺手做了一下。我这里的实现比较简单，基本上就是模拟算术运算，大概分成如下几步&lt;/p&gt;&lt;p&gt;&lt;span style="color: black; font-family: Consolas; font-size: 9pt; background-color: white;"&gt; &lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;&amp;nbsp; 125&lt;br /&gt;&lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;x&amp;nbsp;&amp;nbsp;11&lt;br /&gt;&lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;-------&lt;br /&gt;&lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;&amp;nbsp;   125&lt;br /&gt;&lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;&amp;nbsp;125&lt;br /&gt;&lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;--------&lt;br /&gt;&lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black; font-family: Courier; font-size: 9pt; background-color: white;"&gt;1375&lt;/span&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;将乘数每位与乘数相乘，获取到一个m*n的矩阵&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;将矩阵错位相加，得到输出数组&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-size: 10pt;"&gt;对输出中数组进行进位运算&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;一个简单的实现如下&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: black; font-size: 9pt;"&gt;&lt;span style="font-family: Consolas; background-color: white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;static&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;string&lt;span style="color: black;"&gt; Multiplication(&lt;span style="color: blue;"&gt;string&lt;span style="color: black;"&gt; num1, &lt;span style="color: blue;"&gt;string&lt;span style="color: black;"&gt; num2)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; input1 = num1.Select(i =&amp;gt; (&lt;span style="color: blue;"&gt;int&lt;span style="color: black;"&gt;)(i - &lt;span style="color: maroon;"&gt;'0'&lt;span style="color: black;"&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; input2 = num2.Select(i =&amp;gt; (&lt;span style="color: blue;"&gt;int&lt;span style="color: black;"&gt;)(i - &lt;span style="color: maroon;"&gt;'0'&lt;span style="color: black;"&gt;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: green;"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 宋体; background-color: white;"&gt;把&lt;/span&gt;&lt;span style="color: green;"&gt;&lt;span style="font-family: Consolas; background-color: white;"&gt;num1&lt;/span&gt;&lt;span style="font-family: 宋体; background-color: white;"&gt;依次和&lt;/span&gt;&lt;span style="font-family: Consolas; background-color: white;"&gt;num2&lt;/span&gt;&lt;span style="font-family: 宋体; background-color: white;"&gt;每位相乘，获取到一个&lt;/span&gt;&lt;span style="font-family: Consolas; background-color: white;"&gt;m*n&lt;/span&gt;&lt;span style="font-family: 宋体; background-color: white;"&gt;的矩阵&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Consolas; background-color: white;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; rectangel = input2.Select(i =&amp;gt; input1.Select(j =&amp;gt; j * i).ToArray()).ToArray();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: green;"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 宋体; background-color: white;"&gt;将矩阵错位相加，得到输出数组&lt;/span&gt;&lt;span style="font-family: Consolas; background-color: white;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;span style="color: black;"&gt; result = &lt;span style="color: blue;"&gt;new&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;int&lt;span style="color: black;"&gt;[num1.Length + num2.Length];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;for&lt;span style="color: black;"&gt; (&lt;span style="color: blue;"&gt;int&lt;span style="color: black;"&gt; row = 0; row &amp;lt; num2.Length; row++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;for&lt;span style="color: black;"&gt; (&lt;span style="color: blue;"&gt;int&lt;span style="color: black;"&gt; column = 0; column &amp;lt; num1.Length; column++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result[column + row + 1] += rectangel[row][column];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: green;"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 宋体; background-color: white;"&gt;对输出中数组进行进位运算&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="background-color: white;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;for&lt;span style="color: black;"&gt; (&lt;span style="color: blue;"&gt;int&lt;span style="color: black;"&gt; i = result.Length - 1; i &amp;gt;= 0; i--)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;span style="color: black;"&gt; (result[i] &amp;lt; 10)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;continue&lt;span style="color: black;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result[i - 1] += result[i] / 10;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result[i] %= 10;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;new&lt;span style="color: black;"&gt;&lt;span style="color: blue;"&gt;string&lt;span style="color: black;"&gt;(result.Select(i =&amp;gt; (&lt;span style="color: blue;"&gt;char&lt;span style="color: black;"&gt;)(i += &lt;span style="color: maroon;"&gt;'0'&lt;span style="color: black;"&gt;)).ToArray());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;当然，这个只是一个算法练习，真正在实际应用中如果用到了大数运算是没必要用这个重复轮子的，在.net 4.0中引入了System.Numerics.BigInteger结构，可以实现不限长度的大数运算，比我的这个潦草地实现要凶猛得多的。&lt;/p&gt;  &lt;img src="http://www.cnblogs.com/TianFang/aggbug/2382830.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/03/06/2382830.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TianFang/archive/2012/03/04/2379342.html</id><title type="text">布隆过滤器（Bloom Filter）</title><summary type="text">网上找的两篇介绍布隆过滤器（Bloom Filter）的文章.1. 数学之美系列二十一 － 布隆过滤器（Bloom Filter）在日常生活中，包括在设计计算机软件时，我们经常要判断一个元素是否在一个集合中。比如在字处理软件中，需要检查一个英语单词是否拼写正确（也就是要判断它是否在已知的字典中）；在 FBI，一个嫌疑人的名字是否已经在嫌疑名单上；在网络爬虫里，一个网址是否被访问过等等。最直接的方法就是将集合中全部的元素存在计算机中，遇到一个新元素时，将它和集合中的元素直接比较即可。一般来讲，计算机中的集合是用哈希表（hash table）来存储的。它的好处是快速准确，缺点是费存储空间。当集..</summary><published>2012-03-04T08:29:00Z</published><updated>2012-03-04T08:29:00Z</updated><author><name>天方</name><uri>http://www.cnblogs.com/TianFang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TianFang/archive/2012/03/04/2379342.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TianFang/archive/2012/03/04/2379342.html"/><content type="html">&lt;p&gt;  网上找的两篇介绍&lt;a href="http://en.wikipedia.org/wiki/Bloom_filter"&gt;布隆过滤器（Bloom Filter）&lt;/a&gt;的文章.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. 数学之美系列二十一 － 布隆过滤器（Bloom Filter）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在日常生活中，包括在设计计算机软件时，我们经常要判断一个元素是否在一个集合中。比如在字处理软件中，需要检查一个英语单词是否拼写正确（也就是要判断它是否在已知的字典中）；在 FBI，一个嫌疑人的名字是否已经在嫌疑名单上；在网络爬虫里，一个网址是否被访问过等等。最直接的方法就是将集合中全部的元素存在计算机中，遇到一个新元素时，将它和集合中的元素直接比较即可。一般来讲，计算机中的集合是用哈希表（hash table）来存储的。它的好处是快速准确，缺点是费存储空间。当集合比较小时，这个问题不显著，但是当集合巨大时，哈希表存储效率低的问题就显现出来了。比如说，一个象 Yahoo,Hotmail 和 Gmai 那样的公众电子邮件（email）提供商，总是需要过滤来自发送垃圾邮件的人（spamer）的垃圾邮件。一个办法就是记录下那些发垃圾邮件的 email 地址。由于那些发送者不停地在注册新的地址，全世界少说也有几十亿个发垃圾邮件的地址，将他们都存起来则需要大量的网络服务器。如果用哈希表，每存储一亿个 email 地址， 就需要 1.6GB 的内存（用哈希表实现的具体办法是将每一个 email 地址对应成一个八字节的信息指纹 googlechinablog.com/2006/08/blog-post.html，然后将这些信息指纹存入哈希表，由于哈希表的存储效率一般只有 50%，因此一个 email 地址需要占用十六个字节。一亿个地址大约要 1.6GB， 即十六亿字节的内存）。因此存贮几十亿个邮件地址可能需要上百 GB 的内存。除非是超级计算机，一般服务器是无法存储的。&lt;/p&gt;&lt;p&gt;今天，我们介绍一种称作布隆过滤器的数学工具，它只需要哈希表 1/8 到 1/4 的大小就能解决同样的问题。&lt;/p&gt;&lt;p&gt;布隆过滤器是由巴顿.布隆于一九七零年提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。我们通过上面的例子来说明起工作原理。&lt;/p&gt;&lt;p&gt;假定我们存储一亿个电子邮件地址，我们先建立一个十六亿二进制（比特），即两亿字节的向量，然后将这十六亿个二进制全部设置为零。对于每一个电子邮件地址 X，我们用八个不同的随机数产生器（F1,F2, ...,F8） 产生八个信息指纹（f1, f2, ..., f8）。再用一个随机数产生器 G 把这八个信息指纹映射到 1 到十六亿中的八个自然数 g1, g2, ...,g8。现在我们把这八个位置的二进制全部设置为一。当我们对这一亿个 email 地址都进行这样的处理后。一个针对这些 email 地址的布隆过滤器就建成了。（见下图）&amp;nbsp;&lt;/p&gt;&lt;p&gt;现在，让我们看看如何用布隆过滤器来检测一个可疑的电子邮件地址 Y 是否在黑名单中。我们用相同的八个随机数产生器（F1, F2, ..., F8）对这个地址产生八个信息指纹 s1,s2,...,s8，然后将这八个指纹对应到布隆过滤器的八个二进制位，分别是 t1,t2,...,t8。如果 Y 在黑名单中，显然，t1,t2,..,t8 对应的八个二进制一定是一。这样在遇到任何在黑名单中的电子邮件地址，我们都能准确地发现。&lt;/p&gt;&lt;p&gt;布隆过滤器决不会漏掉任何一个在黑名单中的可疑地址。但是，它有一条不足之处。也就是它有极小的可能将一个不在黑名单中的电子邮件地址判定为在黑名单中，因为有可能某个好的邮件地址正巧对应个八个都被设置成一的二进制位。好在这种可能性很小。我们把它称为误识概率。在上面的例子中，误识概率在万分之一以下。 &lt;/p&gt;&lt;p&gt;布隆过滤器的好处在于快速，省空间。但是有一定的误识别率。常见的补救办法是在建立一个小的白名单，存储那些可能别误判的邮件地址。&lt;/p&gt;&lt;p&gt;原文地址：&lt;a href="http://www.google.com.hk/ggblog/googlechinablog/2007/07/bloom-filter_7469.html"&gt;http://www.google.com.hk/ggblog/googlechinablog/2007/07/bloom-filter_7469.html&lt;/a&gt;（不定期抽风中）&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. BloomFilter&amp;#8212;&amp;#8212;大规模数据处理利器&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这篇文章详细介绍了其原理和实现，写的相当不错。本身就是博客园里的一篇文章，这里就直接贴链接了 &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/heaad/archive/2011/01/02/1924195.html"&gt;http://www.cnblogs.com/heaad/archive/2011/01/02/1924195.html&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;    &lt;img src="http://www.cnblogs.com/TianFang/aggbug/2379342.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TianFang/archive/2012/03/04/2379342.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
