表示编程这条路真得好难走,后悔大学没有读信息专业啊。
第七周的作业:
1. 用户登陆
2. 上传/下载文件
3. 不同用户家目录不同
4. 查看当前目录下文件
刚开始没有一点思路,上网查了很多资料,还自学了FTP。吐槽一句,讲师真是太不负责了,作业要求不详细,还没有思路。
要实现通信,需要7个层次:物理层,数据链路(mac地址),网络层(IP),传输层(有标准的数据类型, TCP/IP 三次握手四次断开, UDP),会话层(http,smtp),表示层,应用层。 传输过程中就需要做到的事情是接收和发送,在python中,这部分功能被封装在socket模块的socket类中。
要实现文件上传和下载,肯定是需要两个端口:一个是服务器端(server),另外一个是客户端(client)。大致的交互流程如下:
理清楚思路之后,就是开始写代码了。
server端的代码如下:
import socket import os import sys sys.path.append(‘..‘) from conf import setting com_path = setting.DATABASE def run(): server = socket.socket() server.bind((‘localhost‘,6969)) server.listen() while True: print(‘等待客户端的连入‘) conn, addr = server.accept() print(‘收到来自%s,%s的请求‘%(str(conn),str(addr))) data = conn.recv(1024).decode() server_path = ‘%s\\%s\\%s‘%(com_path[‘path‘],com_path[‘server‘],data) print(‘当前目录下的文件有:‘) print(os.listdir(server_path)) #检查服务器端是否已经有目录存在,要是没有的化,创建一个目录 if os.path.isdir(server_path): print(‘该用户的目录已经存在‘) else: os.mkdir(server_path) print(‘成功在远程端创建%s的目录‘%data) while True: try: data = conn.recv(1024) if len(data) == 0: continue else: cmd, filename = data.decode().split() file_path = "%s\\%s.txt"%(server_path,filename) print(cmd,filename) if cmd == ‘download‘: print(file_path) if os.path.isfile(file_path): with open(file_path,‘rb‘) as f: file_size = os.stat(file_path).st_size conn.send(bytes(str(file_size),encoding=‘utf-8‘)) print(‘已经成功传送了文件大小%s‘%str(file_size)) conn.recv(1024) #服务器端发送文件大小后,接受客户端的相应 for line in f: conn.send(bytes(str(line),encoding=‘utf-8‘)) elif cmd == ‘upload‘: receive_file_size = conn.recv(1024).decode() conn.send(‘准备好接收文件‘.encode()) receive_size = 0 file_total_size = int(receive_file_size) with open(file_path, ‘wb‘) as f: while receive_size < file_total_size: data = conn.recv(1024) receive_size += len(data) f.write(data) print(‘file recv done‘) print(receive_size,file_total_size) print(‘更新后目录下的文件有:‘) print(os.listdir(server_path)) except Exception: print(‘客户端链接断开‘) break server.close()
client端的代码如下:
import socket import sys sys.path.append(‘..‘) import os from conf import setting com_path = setting.DATABASE current_user = None def auth(func): def wrapper(*args,**kwargs): global current_user username, pwd = input(‘请输入您的用户名,密码:‘).strip().split(‘,‘) user_info_path = ‘%s\\%s.txt‘%(com_path[‘path‘],com_path[‘user_info‘]) exist_flag = False not_user = False with open(user_info_path,‘r‘) as f: while not exist_flag: for line in f: if line.startswith(username): if line.strip().split(‘|‘)[1] == pwd: print(‘登录成功‘) current_user = username func() break exist_flag = True not_user = True else: print(‘密码错误‘) if not not_user: print(‘用户不存在‘) return wrapper @auth def run(): client = socket.socket() client.connect((‘localhost‘,6969)) client_path = ‘%s\\%s\\%s‘%(com_path[‘path‘],com_path[‘client‘],current_user) client.send(current_user.encode())#将用户名发送给服务器端,看看是否有这个客户的目录 while True: inp = input(">>:").strip() if len(inp) == 0: continue try: cmd,filename = inp.split() file_path = "%s\\%s.txt"%(client_path,filename) except: print(‘输入有误,请重新输入‘) continue try: if cmd == ‘download‘: client.send(inp.encode()) receive_file_size = client.recv(1024).decode() print(‘server file size‘,receive_file_size) client.send(‘准备好接收文件‘.encode()) if os.path.isdir(client_path): print(‘该用户的目录已经存在‘) else: os.mkdir(client_path) print(‘成功在远程端创建%s的目录‘%data) receive_size = 0 file_total_size = int(receive_file_size) with open(file_path,‘wb‘)as f: data = client.recv(1024) receive_size += len(data) f.write(data) print(‘file recv done‘) print(receive_size,file_total_size) elif cmd == ‘upload‘: # try: if os.path.isfile(file_path): client.send(bytes(inp,encoding=‘utf-8‘)) with open(file_path,‘rb‘) as f: file_size = os.stat(file_path).st_size print(file_size) client.send(bytes(str(file_size),encoding=‘utf-8‘)) print(‘已经成功传送了文件大小%s‘%str(file_size)) client.recv(1024) for line in f: client.send(bytes(str(line), encoding=‘utf-8‘)) # except Exception: # print(‘只能上传文件‘) except Exception: break client.close() run()
本来想在写一个自己的类,然后继承socket类的,但是无奈,老是出现‘OSError: [WinError 10022] 提供了一个无效的参数’错误,这个BUG我也修改不了。所以就放弃了运用面向对象的方法。希望学到以后能回过头来找出今天没有能力解决的原因吧。
原文:http://www.cnblogs.com/little-hunter/p/6417646.html