标签存档: socket

一个上传客户端的python实现(一)

实验室之前要做一个可以上传动漫、视频和海报的客户端。正好当时正在研究如何实现我的小闹钟,于是就决定继续用PyQt做了。其实当时老师是说要MFC,可我完全不会,就说用QT好了(虽然我当时QT也只会Hello World,囧)。

功能需求:

客户端:1、能添加动画信息,如作者,集数、海报等;2、能对视频进行描述,标题、tags等;3、上传要可以断点续传,因为视频可能比较大,所以不能每次从头开始传。

服务端:1、要能同时处理多个请求;2、最后要把文件排列成一个动画一个文件夹,插入数据库时要保证完整性,因为要同时操作多表。

工作流程:先由用户输入元数据,然后从服务器取得海报、视频的上传的远程地址,上传完毕后再调用服务方法移动文件、重命名、插入数据库。

需要技术术:1、GUI编程;2、C/S 编程;3、ftp 协议的实现。

(我fk曹楼的这网络,让我写了快一小时的博没了!)

C/S编程和FTP协议的实现都得用到socket编程。socket是对Tcp/ip 族的一个抽象,可以认为它实现了这些协议并向用户提供了诸如bind(),accept()这些类似的API,不过同时也要记住,socket并不仅限于Tcp/ip协议族。socket用通信双方的地址和端口号来标识一个连接,因而它可以为两台机器上或同一台机器上占用不同端口号的两个进程提供通信方式。有关更多的资料可以参考以下两个地址:

http://www.chinaunix.net/jh/4/198859.html

http://learn.akae.cn/media/ch37.html

等我看了挺多的资料准备开始动手编的时候,我发现了另一个好东西:rpyc。它将这些通信过程封装起来,使客户端和服务端的通信就像调用普通的函数一样简单,真是相当方便啊,不过有一个缺点就是它使用了BaseException,这使得你必须手动打印错误信息,如果不使用log的话。虽然最后没有直接用socket,不过看了这么多还是很有好处的。

FTP协议的实现方面先在网上找了找现有的代码,发现都太繁琐了,又由于其实上传文件和和服务端完全可以分开,因而不用修改普通的FTP服务器。于是决定自己用ftplib来实现客户端,服务端的话就用普通的FTP服务器如Serv-U,Xlight之类的。自己写了写简单的代码来测试下ftplib,发现里面的函数太多了,眼睛都看花了,于是除了真正的传输二进制信息的时候外,基本都是自己用ntransfercmd()得到socket连接,自己发送命令。有个小trick,在得到服务端当前目录文件列表的时候,如果用ftp.nlst()的话,在最后得到结果时是调用了retrlines(),它会设定TYPE A,因而在传输前要手动地TYPE I,否则传输出出错。

在具体实现的时候碰到了一个问题。RFC959里讲到:STOR 会引起服务器DTP接受经过数据连接传送的数据并将这些数据存储为服务器端的一个文件,如果在路径参数里指定的文件在服务器端已经存在,那么这个文件会被传送过来的数据覆盖。如果指定的文件不存在则会在服务器端新建一个文件。而APPE 则引起服务DTP接受从数据连接传送过来的数据并存储在服务器端的一个文件里。如果指定的文件在服务器端已经存在,则这个数据会附加到文件的后面;否则服务器端会创建这个文件。

但是在实际的程序里测试的结果是,如果文件不存在,那么STOR就正常地工作,就像平常上传一个文件一样,APPE则报错说找不到文件,如果文件存在的话,那么STOR也会在设置了REST的地方开始传输,APPE表现相同,也就是说STOR并没有被传送过来的数据覆盖。我猜测可能和所用的ftp服务端对命令的实现的不同有关吧,本机上使用的是Xlight FTP服务器。为了防止在别的FTP服务器上得到不同的结果,在传输前先做判断,如果文件已经存在,则用APPE,否则STOR。