最近在公司需要写一些协议的客户端,也就趁此机会好好整理一下这些协议,第一个就是SCP协议。查阅了一些资料和一些开源的源码,基本了解这个协议的基本内容。
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。
scp使用方法
1、获取远程服务器上的文件
scp root@remote:/tmp/111 /home
2、获取远程服务器上的目录
scp -r root@remote:/tmp/111/ /home
3、将本地文件上传到服务器上
scp /home/111 root@remote:/tmp
4、将本地目录上传到服务器上
scp -r /tmp/111/ root@remote:/tmp/
SCP协议本身的部分主要描述在一下两个网页:
英文原文:http://blogs.oracle.com/janp/entry/how_the_scp_protocol_works
中文翻译:http://blog.xiaket.org/2010/05/18/how-scp-protocol-works/
另外SCP协议也可以借助SFTP来发送和接收文件,另外再写一篇文章记录。
具体程序就不给了,可以参考一些开源的代码,目前主要看的putty,只要实现了SSH通道,SCP本身这个协议还是比较简单的。
自己依据上面的文档整理了份如下:
1) 协议工作方式
scp [options] [user@]host1:]file1 []... [ [user@]host2:]file2
scp会先解析命令行参数, 然后打开一个到远程服务器的连接. 再通过这个连接起另一个scp进程, 这个进程的运行方式可以是源模式(source)也可以是宿模式(sink). (前者是数据提供者, 源头, 以源模式运行的scp进程后面会被称作是源端。后者是数据的目的地, 归宿, 以宿模式运行的scp进程后面会被称作是宿端)前者读取文件并通过SSH连接发送到另一端, 后者通过SSH连接接收文件. 源模式和宿模式是通过-f (from)和 -t (to)这两个隐藏选项来启动的。 这两个参数仅供命令内部使用, 因此没写进文档。
源端
协议信息是由文本和二进制数据混合构成的。例如, 当我们要传出一个普通文件时, 协议消息的类型, 文件的权限位, 长度及文件名都会以文本的方式发送, 接着在一个换行符后发送文件的内容。我们在后面会更详细地讨论这一点. 协议消息内容可能类似:
C0644 299 group
二进制数据传输前需要传输的文本信息可能更多。源端会一直等宿端的回应, 直到等到回应才会传输下一条协议文本。在送出最后一条协议文本后, 源端会传出一个ASCII字符’\0′来表示真正文件传输的开始。当文件接收完成后, 宿端会给源端发送一个’\0′。
宿端
来自源端的每条消息和每个传输完毕的文件都需要宿端的确认和响应。宿端会返回三种确认消息: 0(正常), 1(警告)或2(严重错误, 将中断连接)。消息1和2可以跟一个字符串和一个换行符, 这个字符串将显示在scp的源端。无论这个字符串是否为空, 换行符都是不可缺少的。
2) 协议消息类型
Cmmmm filesize filename
C表示传输单个文件, 其中mmmm是文件的权限位,filesize是文件大小,filename是文件名称。
例: C0644 299 group
Dmmmm 0 dirname
D表示开始整个目录的递归复制,其中mmmm是目录的权限位,0是文件长度,此处将会忽略, 但是不可缺少,dirname是目录名称。
例: D0755 0 docs
E
E表示目录的结束(D-E这一对可以嵌套使用, 这也是我们能正常递归复制目录树的原因。)
例:E
Txxxx 0 yyyy 0
T表示时间,xxxx是修改时间,yyyy是访问时间。
例:T1183828267 0 1183828267 0
当SCP命令行给出-p选项时, 这一类协议消息用来传输所传递的文件的修改时间和访问时间。 时间记录了从UTC 1970.01.01 00:00:00到现在所经历的秒数。
传完了以上这些消息后就开始传文件数据了。宿端从数据流中读取之前协议消息中指定的文件长度。 D和T需要在其他消息之前指定。这是因为如果这两类消息放在其他消息之后, 这两类消息的内容具体是消息还是数据就不清楚了. 我们可以总结如下:
传完了C类消息后开始传输文件数据。
在传完了D类消息后, 要么出现C类消息, 要么出现E类消息。
最大文件大小和文件完整性
scp所能传输的最大文件大小是由scp协议, scp软件, 操作系统以及文件系统综合决定的. 由于OpenSSH用long long int来放文件大小, 因此理论上可以传输的最大文件大小是2^63 Byte. 给一个参考值, 2^40 Byte的大小是1T. 这意味着我们可以认为协议本身没有文件大小的限制.
3) 协议工作过程
源端 宿端
不论源端还是宿端发出命令 \0
T1183832947 0 1183833956 0(\n) \0
D0755 0 testdir(\n) \0
T1183833773 0 1183833956 0(\n) \0
C0644 5 test(\n) \0
Hello(\0) \0
E(\n) \0
注意无论是源端发起scp –t file命令,还是宿端发起scp –f file命令,宿端都是先发送一个字符’\0’。上面只是为了每行对应分行书写,不存在隐含回车换行,实际发送需要的结束字符在括号中给出。这个例子是发送testdir目录下的test文件,并保留目录和文件的时间属性。在D和E之间还可以重复之间的三行发送其他文件,并且可以嵌套DE发送子目录。