总结
使用Python的socket和socketserver模块实现ftp文件服务器。不是很难,但在粘包的问题上纠缠了不少时间。解决办法是发送文件信息之后等待一段时间。
1 #!/usr/bin/python 2 #coding:utf-8 3 ''' 4 ftp文件上传 服务器端 5 ''' 6 7 import socketserver 8 import os 9 10 11 class myFtpServer(socketserver.BaseRequestHandler): 12 def setup(self): 13 pass 14 15 def handle(self): 16 dir = r'F:\temp' #存放接收文件的目录 17 18 print('Connected %s:%d' %self.client_address) 19 while True: #持续接收文件 20 #接收文件的名称和大小 21 fileInfo = self.request.recv(1024) 22 if fileInfo.decode('utf-8') == 'exit': 23 break 24 filename, filesize = fileInfo.decode('utf-8').strip().split('|') 25 filePath = os.path.join(dir, filename) #创建文件存放路径 26 print('Receiving file:%s, filesize:%s'%(filename, filesize)) 27 with open(filePath, 'wb') as f: 28 recvsize = 0 29 while True: #持续接收文件内容 30 if recvsize == int(filesize): #当接收的大小与文件大小相等时结束接收 31 break 32 self.data = self.request.recv(1024) 33 recvsize += len(self.data) 34 f.write(self.data) 35 print('upload succeed!!') 36 print(recvsize) 37 print('Disconnected %s:%d.' %self.client_address) 38 ''' 39 def handle(self): 40 base_path = '' 41 conn = self.request 42 print( 'connected...') 43 while True: 44 pre_data = conn.recv(1024) 45 #获取请求方法、文件名、文件大小 46 file_name,file_size = pre_data.decode('utf-8').split('|') 47 48 #已经接收文件的大小 49 recv_size = 0 50 #上传文件路径拼接 51 file_dir = os.path.join(base_path,file_name) 52 f = open(file_dir,'wb') 53 Flag = True 54 while Flag: 55 #未上传完毕, 56 if int(file_size)>recv_size: 57 #最多接收1024,可能接收的小于1024 58 data = conn.recv(1024) 59 recv_size+=len(data) 60 #上传完毕,则退出循环 61 else: 62 recv_size = 0 63 Flag = False 64 #写入文件 65 f.write(data) 66 print('upload successed.') 67 f.close() 68 def finish(self): 69 pass 70 71 ''' 72 if __name__ == '__main__': 73 addr = ('127.0.0.1', 9999) 74 sk = socketserver.ThreadingTCPServer(addr, myFtpServer) 75 sk.serve_forever()