觉得翻译的很好,很有价值,原文链接:http://blog.chinaunix.net/u2/70711/showart_1164485.html
参考文献:http://www.hypothetic.org/docs/msn/client/file_transfer.php
文件传输协议MSNFTP
文件传输协议MSNFTP不是MSN Messenger 协议的一部分,但是它却包含在官方客户端中。它与FTP,还有其它文件传输协议没有任何关系。
总揽:
在邀请(invitation stage)阶段,双方商议确定谁是服务器,谁是客户端,哪台电脑发送,哪台电脑接收,要传输的文件叫什么名字,对话的认证cookie。发送方一般做服务器,但是可能要请求接收者服务。一旦客户机和服务器建立连接,MSNFTP就开始在这两个电脑之间交换成行的数据,就像在NS或者SB服务器上的对话一样。在这个初始化的阶段,两个电脑协商一个协议,接收者给出通行证和认证cookie,发送方回复文件的大小。然后,发送方以定长块的二进制数据的方式发送文件。接收方可以在任何时候取消传输。
建立连接:
在邀请阶段,两个电脑协商一个或者两个ip地址和端口,让客户去连接。假如只给出一对ip地址和端口,客户就直接连接这个接口,同时服务器需要在这个端口监听连接发生。假如有两对ip地址和端口被给与,服务器需要在这两个端口监听,客户端要同时尝试去连接这两个ip地址和端口,一旦一个连接一经建立,双方就停止尝试在其它端口连接。
协议:
正文段(text section)就像登陆一个通知服务器(notification server)一样,除了没有传输ID,还有就是假如任意一方传输一个无效的命令,另一方就仅仅关闭连接,而不会传回一个错误信息。
首先:接收方传送一个VER命令,附带它支持的MSNFTP版本号作为参数。官方客户端只支持MSNFTP。发送方回复一个VER命令,包括一个选取的协议。
接着:接收方传送一个USR命令,用用户名和认证cookie作为参数。发送方回复FIL命令,带着唯一参数—要发送文件的长度。官方客户端用这个数据而不是在邀请时给出的长度。
接收方传送命令TFR告知对方,准备接收。接下来,发送方开始发送数据。
关于MSNFTP block:
一个MSNFTP块由一个头部和主体构成,头部表明文件是否成功传输完毕,(如果没有)表示这个块中主体部分包含的要传输的数据的字节数。主体包含文件的确定数目的字节。
头部有3字节长。如果文件没有完成传送,第一字节是0,最后两个字节表示主体的长度--等于第二个字节加上256乘以第三个字节。例如,主题中的字节数是2045(官方客户端的默认字节数),那么第二个字节是253,第三个字节是7,253+256*7 = 2045.一旦整个文件已经被成功传输,一个头部第一个字节是1,后两个字节是0,主体为空的块被发送出去。
下边是一个成功的传输过程举例:
<o> Incoming Connection on Port: 6891
<<< VER MYPROTO MSNFTP
>>> VER MSNFTP
<<< USR myname@msn.com 93301
>>> FIL 13
<<< TFR
>>> 0, 13, 0, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33
>>> 1, 0, 0
<<< BYE 16777989
And here is a failed negotiation:
<o> Incoming Connection on Port: 6891
<<< VER MYPROTO
<o> Disconnect
早先MSN协议上的文件传输
在第三方客户端和官方客户端之间传送文件用的是MSNP2P协议。这种传输发生SB连接建立之后,也就是说没有像MSNFTP协议那样独立的TCP连接。典型的过程如下边所述:
消息体介绍:
<!--[if !supportLists]-->1,<!--[endif]-->当客户端想要传输文件,它发送带有Content-Type被设置为application/x-msnmsgrp2p的消息给接收方;
<!--[if !supportLists]-->2,<!--[endif]-->Content-type之后是P2P-Dest头部。
<!--[if !supportLists]-->3,<!--[endif]-->一个p2p-dest头部后边是48个字节,包括有以下顺序的这些信息:
<!--[if !supportLists]-->一, <!--[endif]-->Channel SessionID - 4 bytes
<!--[if !supportLists]-->二, <!--[endif]-->ID - 4 bytes
<!--[if !supportLists]-->三, <!--[endif]-->Offset - 8 bytes
<!--[if !supportLists]-->四, <!--[endif]-->Total Data Size - 8 bytes
<!--[if !supportLists]-->五, <!--[endif]-->Message Size - 4 bytes
<!--[if !supportLists]-->六, <!--[endif]-->Flags - 4 bytes
<!--[if !supportLists]-->七, <!--[endif]-->Acknowledgement ID - 4 bytes
<!--[if !supportLists]-->八, <!--[endif]-->Acknowledgement UID - 4 bytes
<!--[if !supportLists]-->九, <!--[endif]-->Acknowledgement Size - 8 bytes
<!--[if !supportLists]-->4,<!--[endif]-->上面的48字节头部以信息INVITE MSNMSGR <email>@hotmail.com MSNSLP/1.0结尾。
<!--[if !supportLists]-->5,<!--[endif]-->接下来是一些头部像:To,From指示文件的发送方和接收方。
<!--[if !supportLists]-->6,<!--[endif]-->接着是第二个Content-Type头部,在这里头部被设置为application/x-msnmsgr-sessionreqbody。
<!--[if !supportLists]-->7, <!--[endif]-->然后是头部EUF-GUID它的值指示此邀请是一个文件传输还是人物图标传输。是文件传输,EUF-GUID被设置成{5D3E02AB-6190-11D3-BBBB-00C04F795683}。
<!--[if !supportLists]-->8, <!--[endif]-->接着是SessionID头部。当真正的文件数据被传输时,在48字节的P2P头部中的Chanal SessionID被设置为这个值。所以,当前的SessionID头部是告诉接收方当收到的MSNP2P消息的Channel SessionID被设置为这个值时,数据块包含着文件数据。
<!--[if !supportLists]-->9, <!--[endif]-->接着是AppID指示文件传输的类型,人物图像还是文件传输,如果是文件传输AppID被设为2:
AppID:2\r\n
10, 接下来就是Context部分了。文本的指示base64编码的250字节的串,包括了文件名字和文件长度等信息。
下边是一个典型的请求消息:
>>> MSG 6 D 1348\r\n
MIME-Version: 1.0\r\n
Content-Type: application/x-msnmsgrp2p\r\n
P2P-Dest: some_body@hotmail.com\r\n
\r\n
\000\000\000\000-\037\216#\000\000\000\000\000
\000\000\000\271\004\000\000\000\000\000\000
\262\004\000\000\000\000\000\000.\371\234\020\000\000
\000\000\000\000\000\000\000\000\000\000INVITE MSNMSGR some_body@hotmail.com MSNSLP/1.0\r\n
To: <msnmsgr:some_body @hotmail.com>\r\n
From: <msnmsgr:this_buddy@hotmail.com>\r\n
Via: MSNSLP/1.0/TLP ;branch={7E873D59-824B-5084-3544-90B83C8D3C40}\r\n
CSeq: 0\r\Content-Type: application/x-msnmsgr-sessionreqbody\n
Call-ID: {9C468B3E-4BEA-1C6E-9E6D-1BE9455F8147}\r\n
Max-Forwards: 0\r\n
r\n
Content-Length: 865\r\n
\r\n
EUF-GUID: {5D3E02AB-6190-11D3-BBBB-00C04F795683}\r\n
SessionID: 1189641425\r\n
Context: PgIAAAIAAAAsAQAAAAAAAAAAAAB0AGUAcwB0ADEAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n
然后接收者回复一个MSNP2P消息,接受传输邀请,消息大概如下:
<<< MSG some_body@hotmail.com Somebody 487\r\n
MIME-Version: 1.0\r\n
Content-Type: application/x-msnmsgrp2p\r\n
P2P-Dest: this_buddy@hotmail.com\r\n
\r\n
\000\000\000\000\016\212\235\020\000\000\000\000\000\000\000
\000T\001\000\000\000\000\000\000T\001\000\000\000\000\000\000
\205\360\203%\000\000\000\000\000\000\000\000\000\000\000\000
MSNSLP/1.0 200 OK\r\n
To: <msnmsgr:this_buddy@hotmail.com>\r\n
From: <msnmsgr:some_body@hotmail.com>\r\n
Via: MSNSLP/1.0/TLP ;branch={7E873D59-824B-5084-3544-90B83C8D3C40}\r\n
CSeq: 1\r\n
Call-ID: {9C468B3E-4BEA-1C6E-9E6D-1BE9455F8147}\r\n
Max-Forwards: 0\r\n
Content-Type: application/x-msnmsgr-sessionreqbody\r\n
Content-Length: 26\r\n
\r\n
SessionID: 1189641425\r\n
\r\n
\000\000\000
当真正的文件数据被传送的时候,发送方设置Channel SessionID段等于SessionID 。
需要注意的是,任何MSNP2P信息在任何数据之前首先包含48字节的头部信息。当要传输的文件太大,以至于不能一次传输完,他将会被分开通过多次MSNP2P信息传送。那时,Message Size字段指代本次消息传送的文件字节数,而Total Data Size字段指代被传送的文件的总长度。所以,接收方要通过检测P2P头部字段来判断文件传输是否完成。(通常情况下,Offset+Message Size = Total Data Size 表示文件传输完毕)。
以上内容译自http://www.hypothetic.org/docs/msn/client/file_transfer.php 。
为尊重作者,转载请注明出处 ,谢谢。
浙公网安备 33010602011771号