项目: 基于Python socket模块实现的简单 ftp 项目:
需要 自己创建一个 info 文件 用来存储用户信息
服务器:
1 import socket 2 import pickle 3 import struct 4 import os 5 import time 6 7 ''.startswith('vip') 8 9 class Mysocket(socket.socket): 10 """此类 重写socket类的reve和send方法, 表示如果发送的是字符串 直接调用这两个方法即可""" 11 12 def __init__(self, encoding='utf-8'): 13 self.encoding = encoding 14 super().__init__() 15 16 def my_reve(self, num): 17 msg = self.recv(num).decode(self.encoding) 18 return msg 19 20 def my_send(self, msg): return self.send(msg.encode(self.encoding)) 21 22 23 class ServerFTP(socket.socket): 24 def __init__(self): 25 self.flag = True 26 self.path_dir = None 27 self.vip = '' 28 super().__init__() 29 30 def up_vip(self,dict_client, login_dict_2): 31 try: 32 if not ('vip' in self.path_dir): 33 print(dict_client['username']) 34 old_name = dict_client['username'] 35 self.vip = 'vip' 36 print(7758521) 37 self.new_name = self.vip + dict_client['username'] 38 os.rename(old_name,self.new_name) 39 login_dict_2['vip_ret'] = '升级成功' 40 except Exception:login_dict_2['vip_ret'] ='您已经是vip了,扩容失败' 41 42 43 def upload(self, path_dir, dict_client_2, login_dict_2,dict_client): 44 file_name = dict_client_2['file_name'] 45 file_size = dict_client_2['file_size'] 46 now_dir_name = os.path.join(path_dir, file_name) 47 with open(now_dir_name, 'wb') as f: 48 while file_size>0: 49 content = self.conn.recv(1024) 50 f.write(content) 51 file_size -= len(content) 52 login_dict_2['listdir'] = os.listdir(path_dir) 53 print(1) 54 55 56 def download(self, path_dir, dict_client_2, login_dict_2): 57 file_path = os.path.join(path_dir, dict_client_2['file_name']) 58 dict_client_2['file_size'] = os.path.getsize(file_path) 59 file_size = dict_client_2['file_size'] 60 self.conn.send(struct.pack('i', file_size)) 61 with open(file_path, 'rb') as f: 62 while file_size: 63 if file_size<1024:content = f.read(file_size) 64 else:content = f.read(1024) 65 self.conn.send(content) 66 file_size -= len(content) 67 login_dict_2['listdir'] = os.listdir(path_dir) 68 69 70 def login(self, dict_client): 71 login_dict = {} 72 with open('../db/info', encoding='utf-8') as f: 73 for line in f: 74 if dict_client['username'] + '\t' + dict_client['password'] == line.strip(): 75 login_dict['opt'] = '登录成功' 76 try: 77 name = 'vip'+dict_client['username'] 78 self.path_dir = os.path.join(os.path.dirname(__file__), name) 79 login_dict['listdir'] = os.listdir(self.path_dir) 80 except Exception: 81 self.path_dir = os.path.join(os.path.dirname(__file__), dict_client['username']) 82 login_dict['listdir'] = os.listdir(self.path_dir) 83 try: 84 login_dict['容量'] = '%s/%s (单位:字节)' % ( 85 os.path.getsize(os.path.dirname(__file__) + '/vip' +dict_client['username']), 1024 * 10000) 86 except Exception: 87 login_dict['容量'] = '%s/%s (单位:字节)' % ( 88 os.path.getsize(os.path.dirname(__file__) + '/' + dict_client['username']), 1024 * 100) 89 self.conn.send(struct.pack('i', len(pickle.dumps(login_dict))) + pickle.dumps(login_dict)) 90 while self.flag: 91 self.main_2(dict_client) 92 93 return 94 login_dict['opt'] = '登录失败' 95 self.conn.send(struct.pack('i', len(pickle.dumps(login_dict))) + pickle.dumps(login_dict)) 96 return 97 98 99 def register(self, dict_client): 100 register_dict = {} 101 with open('../db/info', 'r+', encoding='utf-8') as f: 102 for line in f: 103 if dict_client['username'] == line.strip().split('\t')[0]: 104 register_dict['opt'] = '用户名已存在' 105 self.conn.send(struct.pack('i', len(pickle.dumps(register_dict))) + pickle.dumps(register_dict)) 106 return 107 register_dict['opt'] = '注册成功' 108 f.seek(0, 2) 109 f.write(dict_client['username'] + '\t' + dict_client['password'] + '\n') 110 os.mkdir(dict_client['username']) 111 path_user = os.path.join(os.path.dirname(__file__), dict_client['username']) 112 for i in range(3): 113 os.mkdir(os.path.join(path_user, str(i))) 114 self.conn.send(struct.pack('i', len(pickle.dumps(register_dict))) + pickle.dumps(register_dict)) 115 time.sleep(5) 116 return 117 118 119 def main_2(self, dict_client): 120 login_dict_2 = {} 121 dict_client_2 = pickle.loads(self.conn.recv(struct.unpack('i', self.conn.recv(4))[0])) # reve_2 接受 选择和文件内容 122 if dict_client_2['opt'] == '1': 123 self.path_dir = os.path.join(os.path.dirname(self.path_dir),self.vip+os.path.basename(self.path_dir)) 124 self.path_dir = os.path.join(self.path_dir, dict_client_2['filename']) 125 login_dict_2['listdir'] = os.listdir(self.path_dir) 126 print('进入下一层了') 127 elif dict_client_2['opt'] == '2': 128 print('想访问上一层了') 129 print(self.path_dir) 130 self.path_dir_2 = os.path.dirname(self.path_dir) 131 print(self.path_dir_2) 132 if self.path_dir_2 == os.path.dirname(__file__): 133 login_dict_2['listdir'] = '已经到底了 没有内容了哦' 134 else: 135 self.path_dir = self.path_dir_2 136 login_dict_2['listdir'] = os.listdir(self.path_dir) 137 elif dict_client_2['opt'] == '3': 138 print('想传东西了') 139 self.upload(self.path_dir, dict_client_2, login_dict_2, dict_client) 140 print('传完了') 141 elif dict_client_2['opt'] == '4': 142 self.download(self.path_dir, dict_client_2, login_dict_2) 143 elif dict_client_2['opt'] == '5': 144 self.up_vip(dict_client,login_dict_2) 145 elif dict_client_2['opt'] == '6': 146 self.flag = False 147 return 148 self.conn.send(struct.pack('i', len(pickle.dumps(login_dict_2))) + pickle.dumps(login_dict_2)) 149 150 def main(self, conn): 151 while 1: 152 head_client = conn.recv(4) 153 try: 154 dict_client = pickle.loads(conn.recv(struct.unpack('i', head_client)[0])) 155 print('来看看他发的啥哈哈哈') 156 if dict_client['opt'] == '1': 157 self.login(dict_client) 158 elif dict_client['opt'] == '2': 159 self.register(dict_client) 160 except struct.error: 161 return 162 163 164 def __call__(self, *args, **kwargs): 165 sk = socket.socket() 166 sk.bind(('192.168.19.15', 8888)) 167 sk.listen() 168 while 1: 169 self.conn, addr = sk.accept() 170 print('连上了') 171 self.main(self.conn) 172 self.conn.close() 173 174 175 if __name__ == '__main__': 176 ftp_s = ServerFTP() 177 ftp_s()
客户端:
1 import socket 2 import hashlib 3 import pickle 4 import struct 5 import os 6 7 8 class Mysocket(socket.socket): 9 """此类 重写socket类的reve和send方法, 表示如果发送的是字符串 直接调用这两个方法即可""" 10 11 def __init__(self, encoding='utf-8'): 12 self.encoding = encoding 13 super().__init__() 14 15 def my_reve(self, num): 16 msg = self.recv(num).decode(self.encoding) 17 return msg 18 19 def my_send(self, msg): return self.send(msg.encode(self.encoding)) 20 21 22 def upload(login_dict): 23 file_dir = input('>>>请输入文件名:').strip() 24 file_name = os.path.basename(file_dir) 25 login_dict['file_name'] = file_name 26 file_size = os.path.getsize(file_dir) 27 login_dict['file_size'] = file_size 28 sk.send(struct.pack('i', len(pickle.dumps(login_dict))) + pickle.dumps(login_dict)) # send_2 : 发送选择 或者 选择和文件 29 with open(file_dir, 'rb') as f: 30 while file_size: 31 content = f.read(1024) 32 sk.send(content) 33 file_size -= len(content) 34 35 36 def download(login_dict): 37 file_name = input('>>>下载文件的名字:').strip() 38 down_path = input('>>>本地下载文件路径:').strip() 39 login_dict['file_name'] = file_name 40 sk.send(struct.pack('i', len(pickle.dumps(login_dict))) + pickle.dumps(login_dict)) 41 down_file_size = struct.unpack('i', sk.recv(4))[0] 42 with open(down_path, 'wb') as f: 43 while down_file_size: 44 if down_file_size < 1024: 45 content = sk.recv(down_file_size) 46 else:content = sk.recv(1024) 47 f.write(content) 48 down_file_size -= len(content) 49 50 51 def up_vip(usn): pass 52 53 54 def login(dict_server, usn): 55 login_dict = {} 56 print(dict_server['listdir']) 57 while 1: 58 print('1, 进入下级文件目录\n' 59 '2, 返回上层目录\n' 60 '3, 在该目录上传文件\n' 61 '4, 下载该目录下的某个文件\n' 62 '5, 升级为VIP\n' 63 '6, 退出程序') 64 opt = input('>>>请选择功能:').strip() 65 login_dict['opt'] = opt 66 if opt == '1': 67 login_dict['filename'] = input('>>>文件名') 68 sk.send( 69 struct.pack('i', len(pickle.dumps(login_dict))) + pickle.dumps(login_dict)) # send_2 : 发送选择 或者 选择和文件 70 71 elif opt == '3': 72 upload(login_dict) 73 print('上传成功') 74 elif opt == '4': 75 download(login_dict) 76 print('下载成功') 77 elif opt == '5': # 升级VIP还待补充. 78 print('将扩大100倍的容量') 79 up_vip(usn) 80 sk.send( 81 struct.pack('i', len(pickle.dumps(login_dict))) + pickle.dumps(login_dict)) # send_2 : 发送选择 或者 选择和文件 82 83 if opt == '6': 84 global flag 85 flag = False 86 return 87 dict_server_2 = pickle.loads(sk.recv(struct.unpack('i', sk.recv(4))[0])) 88 try: 89 print(dict_server_2['listdir']) 90 except KeyError: 91 print(dict_server_2['vip_ret']) 92 93 94 def main(): 95 while flag: 96 print('1, 登录\n2, 注册') 97 opt = input('>>>选择功能:').strip() 98 if opt != '1' and opt != '2': 99 print('输入错误,程序结束') 100 return 101 dic['opt'] = opt 102 usn = input('>>>Username:').strip() 103 dic['username'] = usn 104 pwd = input('>>>Password:').strip() 105 md5_obj = hashlib.md5(usn.encode('utf-8')) 106 md5_obj.update(pwd.encode('utf-8')) 107 pwd = md5_obj.hexdigest() 108 dic['password'] = pwd 109 dic_pic = pickle.dumps(dic) 110 head = struct.pack('i', len(dic_pic)) 111 sk.send(head + dic_pic) # send 1: 把登录/注册 + 用户名 + 密码发送给服务器 112 head_server = sk.recv(4) 113 dict_server = pickle.loads(sk.recv(struct.unpack('i', head_server)[0])) 114 print(dict_server['opt']) 115 if dict_server['opt'] == '登录成功': 116 print(dict_server['容量']) 117 login(dict_server, usn) 118 119 120 if __name__ == '__main__': 121 flag = True 122 dic = {'opt': '请求的功能', } 123 124 sk = Mysocket() 125 sk.connect_ex(('192.168.19.15', 8888)) 126 127 main() 128 129 sk.close()