python day 14

2019/10/19

看了老师的FTP脚本之后,我下面的代码就是a piece of shit。不忍目睹。

1. 要求

FTP:

1,单独功能实现(进度条,断点续传)

2,整合

3,bin,config,db,lib程序目录

2. 自己写的程序目录

3. models模块

import os, sys

sys.path.append(os.path.dirname(os.path.dirname(__file__)))
import socketserver
import socket
import hashlib
import pickle
from config import settings
import subprocess
import chardet def down_file(conn):
conn.sendall('请输入文件路径'.encode('utf-8'))
filename = conn.recv(1024).decode('utf-8')
print(filename)
path = os.path.join(settings.FILE_DB_DIR, filename)
if not os.path.exists(path):
conn.sendall(b'1000')
filesize = int(conn.recv(1024).decode('utf-8'))
print(filesize)
conn.sendall(b'ack')
has_data = 0
content = bytes('',encoding='ISO-8859-1')
while has_data<filesize:
ret = conn.recv(1024)
# print(chardet.detect(ret))
content += ret
has_data += len(ret)
f = open(path,'wb')
f.write(content)
f.close()
else:
conn.sendall(b'1001')
exist_file_size=os.stat(path).st_size
conn.sendall(str(exist_file_size).encode('utf-8')) def do_command(conn):
conn.sendall('请输入命令'.encode('utf-8'))
com1 = conn.recv(1024).decode('utf-8') # ipconfig
print(com1)
result = subprocess.check_output(com1)
# linux系统是以utf-8默认编码,windows是以gbk默认编码,所以此处result是以gbk编码的bytes,折腾了两个小时
# print(result.decode('gbk'))
conn.sendall(str(len(result)).encode('utf-8')) # 1638
print(conn.recv(1024)) # b'lan'
conn.sendall('ack'.encode('utf-8'))
print(conn.recv(1024)) # b'ack'
result = result.decode('gb2312').encode('utf-8')
# print(chardet.detect(result))
conn.sendall(result) def login(conn, name, pwd):
m = hashlib.md5(bytes('lan', encoding='utf-8'))
m.update(bytes(pwd, encoding='utf-8'))
hex1 = m.hexdigest()
path = os.path.join(settings.CLIENT_DB_DIR, name)
result = pickle.load(open(path, 'rb'))
username, password = result.split('$')
if username == name and password == hex1:
conn.sendall('登录成功'.encode('utf-8'))
return 1
else:
conn.sendall('密码错误'.encode('utf-8'))
return 0 def register(conn, name, pwd):
m = hashlib.md5(bytes('lan', encoding='utf-8'))
m.update(bytes(pwd, encoding='utf-8'))
hex1 = m.hexdigest()
s1 = '$'.join([name, hex1])
print(s1)
path = os.path.join(settings.CLIENT_DB_DIR, name)
pickle.dump(s1, open(path, 'wb'))
conn.sendall('用户{0}注册成功'.format(name).encode('utf-8')) def connect_user(conn, addr1):
inp = '请输入用户名与密码'.encode('utf-8')
conn.sendall(inp)
name = conn.recv(1024).decode('utf-8') pwd = conn.recv(1024).decode('utf-8') inp2 = '1是登录;2是注册,请输入数字进行选择'.encode('utf-8')
conn.sendall(inp2)
ret = conn.recv(1024).decode('utf-8')
print('来自%s的消息:\n>>>%s' % (addr1[0], ret))
if ret == '2':
register(conn, name, pwd)
if ret == '1':
result = login(conn, name, pwd) if result:
while True:
inp3 = '3是执行命令;4是上传文件,请输入数字进行选择'.encode('utf-8')
conn.sendall(inp3)
ret2 = conn.recv(1024).decode('utf-8')
print('来自%s的消息:\n>>>%s' % (addr1[0], ret2))
if ret2 == '3':
do_command(conn)
elif ret2 == '4':
down_file(conn)
elif ret == 'q':
break class MyServer(socketserver.BaseRequestHandler):
def handle(self):
conn, addr2 = self.request, self.client_address
connect_user(conn, addr2)
# size_str = conn.recv(1024).decode('utf-8')
# total_size_int = int(size_str)
# print('来自%s的消息:\n>>>文件大小是%s' % (addr[0], total_size_int))
# has_data = 0
# file_name = conn.recv(1024).decode('utf-8')
# print('来自%s的消息:\n>>>文件名字是%s' % (addr[0], file_name))
# conn.sendall('ack'.encode('utf-8'))
# f = open(file_name, 'wb')
# while True:
# if has_data == total_size_int:
# break
# ret = conn.recv(1024)
# f.write(ret)
# has_data += len(ret)
# f.close() # class MySocket(socket.socket):
# def __init__(self, family=-1, type=-1, proto=-1, fileno=None):
# self.name = None
# self.pwd = None
# super().__init__(family, type, proto, fileno)
#
# def login(self, user, pwd):
# if self.name == user and self.pwd == pwd:
# return True
# else:
# return False
#
# def register(self, user, pwd):
# self.name = user
# m = hashlib.md5()
# m.update(bytes(pwd, encoding='utf-8'))
# password = m.hexdigest()
# self.pwd = password if __name__ == '__main__':
addr = ('192.168.131.1', 9999,)
tcp_server = socketserver.ThreadingTCPServer(addr, MyServer)
tcp_server.serve_forever()

4. settings模块

import os

BASE_DIR = os.path.dirname(os.path.dirname(__file__))
CLIENT_DB_DIR = os.path.join(BASE_DIR, 'db', 'client')
FILE_DB_DIR= os.path.join(BASE_DIR, 'db', 'file')

5. tcp_server模块

import os, sys

sys.path.append(os.path.dirname(os.path.dirname(__file__)))
import pickle
from lib.models import * def main():
addr = ('192.168.131.1', 9999,)
tcp_server = socketserver.ThreadingTCPServer(addr, MyServer)
tcp_server.serve_forever() if __name__ == '__main__':
main()

6. client模块

import os, sys
import socket sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from lib.models import *
import hashlib
import getpass
import chardet
import pickle def recv_com(obj):
file_size = int(obj.recv(1024).decode('utf-8'))
print(file_size) # 1857
has_data = 0
obj.sendall('lan'.encode('utf-8'))
print(obj.recv(1024)) # b'ack
obj.sendall(b'ack')
ret3 = ''
while has_data < file_size:
data = obj.recv(1024)
# print(chardet.detect(data))
ret3 += data.decode('utf-8')
has_data += len(data)
# has_data = len(obj.recv(1024)) 这里还会再执行一次接收数据动作,所以就是这里卡住了。 print(ret3) def load_file(obj):
command1 = obj.recv(1024).decode('utf-8') # 文件路径
print(command1)
file_path = input('文件路径是:\n>>>').strip()
file_name = os.path.split(file_path)[1]
obj.sendall(file_name.encode('utf-8')) ret_code = obj.recv(1024)
if ret_code ==b'1000':
file_size = os.stat(file_path).st_size # int类型
obj.sendall(str(file_size).encode('utf-8'))
obj.recv(1024)
with open(file_path, 'rb') as f:
for i in range(1,file_size+1):
file_content = f.read(1)
obj.sendall(file_content)
sys.stdout.write('\r')
sys.stdout.write('%.2f%% |%s' % (i / file_size * 100, int(i / file_size * 100) * '#'))
sys.stdout.flush()
elif ret_code==b'1001':
pass def connect_server():
obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr = ('192.168.131.1', 9999,)
obj.connect(addr)
ret_str = obj.recv(1024).decode('utf-8')
print('来自%s的消息:\r\n>>>%s' % (addr[0], ret_str))
user = input('请输入用户名:>>>').strip()
obj.sendall(user.encode('utf-8'))
pwd = getpass.win_getpass('password:')
obj.sendall(pwd.encode('utf-8')) result2 = str(obj.recv(1024), encoding='utf-8') # 1是登录;2是注册,请输入数字进行选择
print('来自%s的消息:\r\n>>>%s' % (addr[0], result2,))
inp = input('请输入发送给%s的消息:\n>>>' % addr[0]).strip() # 1
obj.sendall(inp.encode('utf-8')) result2 = str(obj.recv(1024), encoding='utf-8')
print('来自%s的消息:\r\n>>>%s' % (addr[0], result2,)) # 登录成功 while True:
result2 = str(obj.recv(1024), encoding='utf-8')
print('来自%s的消息:\r\n>>>%s' % (addr[0], result2,))
# 3是执行命令;4是上传文件,请输入数字进行选择
inp = input('请输入发送给%s的消息:\n>>>' % addr[0]).strip()
obj.sendall(inp.encode('utf-8')) # 3
if inp == '3':
result2 = str(obj.recv(1024), encoding='utf-8')
print('来自%s的消息:\r\n>>>%s' % (addr[0], result2,)) # 请输入命令
inp = input('请输入发送给%s的消息:\n>>>' % addr[0]).strip()
obj.sendall(inp.encode('utf-8')) # ipconfig
recv_com(obj)
elif inp == '4':
load_file(obj)
elif inp == 'q':
obj.close()
break def main():
'''
客户端主程序
:return:
'''
connect_server()
# ret = obj.recv(1024).decode('utf-8')
# print('来自%s的消息:\n>>>%s' % (addr[0], ret))
# inp = input('请输入要传送的文件路径:\n>>>').strip()
# size = str(os.stat(inp).st_size, encoding='utf-8')
# file_name = os.path.split(inp)[1]
# obj.sendall(size.encode('utf-8'))
# obj.sendall(file_name.encode('utf-8'))
# obj.recv(1024)
# with open(inp, 'rb') as f:
# for line in f:
# if line:
# obj.sendall(line)
# else:
# print('传送完毕')
# break
# obj.close() if __name__ == '__main__':
main()

7. 后记

只实现了多用户md5登录,命令执行,文件传递,进度条显示,并没有实现文件续传功能。

还需要修改。不过也折腾了近5个小时,在编码的转换问题上折腾了好久。

下次一定要记住使用chardet模块的detect方法先检测下编码,然后按照对应的编码方式进行编码与解码。

python day 14: 作业:开发一个能够多用户上传文件的FTP脚本的更多相关文章

  1. java 26 - 9 网络编程之 TCP协议多用户上传文件

    TCP实现多用户上传文件: 需要同时给多用户上传文件,这样就得用多线程来实现. 实际上,这样的话,上传的先后顺序和速度就跟客户端的带宽有关:带宽够,就容易抢占到线程的执行权: 首先,创建个线程类:(这 ...

  2. 【HTTP】boundary 中一个 = 导致HTTP上传文件失败

    (1)#define ABOUNDARY "----=_Resume_002_0CE7_01D1C649.298A8070" (2)#define ABOUNDARY " ...

  3. 朋友封装的一个ASP.NET上传文件的方法

    朋友做了asp.net开发多年,做了这个,自我感觉封装得还不错!!! 代码如下: #region 上传文件的方法 /// <summary> /// 上传文件方法 /// </sum ...

  4. 一个Jmeter模拟上传文件接口的实例

    资料参考:https://blog.csdn.net/u010390063/article/details/78329373 项目中,避免不了要用到很多上传文件.图片的接口,那么碰到这类接口该如何进行 ...

  5. IOS开发教程之put上传文件的服务器的配置及实例分享-备用

    感谢大神分享 1,HTTP常见的方法 GET 获取指定资源 POST 2M 向指定资源提交数据进行处理请求,在RESTful风格中用于新增资源 HEAD 获取指定资源头部信息PUT 替换指定资源(不支 ...

  6. python 从windows上传文件到linux脚本

    import paramiko import datetime import os hostname = '192.168.112.132' username = 'root' password = ...

  7. git从无到有建立一个仓库并上传文件

    第一步,创建仓库 登录自己的码云  第二步,本地操作 1.到你所要上传的文件夹中右键 选择git bash here 2.初始化项目 git init 3.连接远程仓库 刚才我们建立的时候的远程地址就 ...

  8. python 开发一个支持多用户在线的FTP

    ### 作者介绍:* author:lzl### 博客地址:* http://www.cnblogs.com/lianzhilei/p/5813986.html### 功能实现 作业:开发一个支持多用 ...

  9. Python3学习之路~8.6 开发一个支持多用户在线的FTP程序-代码实现

    作业: 开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp s ...

随机推荐

  1. sharding jdbc(sphere) 3.1.0 spring boot配置

    sharding jdbc 2.x系列详解参见https://www.cnblogs.com/zhjh256/p/9221634.html. 最近将sharding jdbc的配置从xml切换到了sp ...

  2. 将本地文件夹添加到git仓库

    1.git init; 2.git add . 3.git commit -m "初始化" 4.git remote add origin https://github.com/g ...

  3. golang几种常用配置文件使用方法总结(yaml、toml、json、xml、ini)

    原文连接: https://blog.csdn.net/wade3015/article/details/83351776 yaml配置文件的使用方法总结 首先介绍使用yaml配置文件,这里使用的是g ...

  4. django在centos生产环境的部署

    # 安装数据库和web服务器nginx # yum install –y nginx mariadb-server # 安装虚拟环境 pip install virtualenv pip instal ...

  5. Bootstrap Table 初始化设置

    $('#ArbetTable').bootstrapTable({ url: '/Interface/GetData', //请求后台的URL(*) method: 'get', //请求方式(*) ...

  6. iOS - 截取数组前几个元素放入新的数组,剩余的放入另外一个数组

    NSArray *array = [NSArray arrayWithObjects:@"Crystal",@"Maisie",@"Lukas&quo ...

  7. 修改Window服务器虚拟内存位置

    系统采用的是windows server2008操作系统,硬件部门在分配磁盘的时候C盘只有50G,其中虚拟内存就占用了30G,再除去操作系统占用空间,可用自由支配空间较小,会出现在部分异常情况下C盘占 ...

  8. QT+OPENCV实现录屏功能

    本文使用QT+opencv来实现对指定窗体画面录制,并保存为avi文件. (1)获取窗体界面 QScreen类有一个grabWindow函数,可以用来获取窗体的画面,这个函数使用很简单,就是传入窗体句 ...

  9. Idea开发环境中,开发springboot类型的项目,如果只引入parent节点,不添加依赖节点,maven是不会加载springboot的任何依赖的

    在SpringBoot类型的项目中,我本来是要使用pringBoot,创建一个Console项目,我原本在pom.xml中添加paren节点了,天真的认为不需要再添加其他任何依赖了,可是接下来的1个小 ...

  10. 静默安装weblogic12c提示INST-07319: Oracle 主目录(O) 位置的验证失败。指定的位置已存在, 是非空目录并且不是有效的 Oracle 主目录

    [xxx@localhost bea12c3]$ java -jar fmw_12.2.1.3.0_wls.jar -silent -responseFile /app/bea12c3/weblogi ...