项目: 基于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()

 

posted @ 2018-07-24 21:39  浮生凉年  阅读(475)  评论(0编辑  收藏  举报