​ 【1】先登录,登录不成功循环登录,直到成功。登录成功后可以选择上传或者下载,上传有对应的文件,可选择上传哪个;下载有对应的文件,可选择下载哪个

​ 【2】登录,上传,下载时最好设置状态码,客户端和服务端约定好状态码,操作成功或者失败后,发送对应的状态码。注意,每一个操作要有唯一的状态码。

​ 比如: 登录成功 100 登录失败 101

​ 注册成功 102 注册失败 103

​ 上传成功 104 上传失败 105

​ 下载成功 106 下载失败 107

​ 【3】也可以用字典: dic = {'operate': 'login', 'result': res} res= True 或 False 表明要进行的操作,以及状态。比较直观

​ 【4】网络之间进行数据传递,最常用的就是json模块。传送一个字典

​ 【5】编程尽量少使用面向过程编程,多使用 函数 + 面向对象 编程

​ 【6】函数中都要用传参的方式,传入conn,sk等,不要用全局变量,便于文件拆分,进行进一步封装。不用全局变量 ,因为将来文件拆分后,全局变量就不能用了。

​ 【7】输入时,容易出错的地方,要进行异常处理(进一步优化)


#server
import os
import sys
import json
import struct
import socket
import hashlib def my_send(conn,dic): #用于发送要 被下载的文件的信息(字典{'filename': filename, 'filesize': filesize});可下载文件列表
str_dic = json.dumps(dic)
b_dic = str_dic.encode('utf-8')
mlen = struct.pack('i', len(b_dic))
conn.send(mlen) # 4个字节 表示字典/列表转成字节之后的长度
conn.send(b_dic) # 具体的字典数据 def my_recv(conn): #用于接收将要上传文件的信息(字典形式)
msg_len = conn.recv(4)
dic_len = struct.unpack('i', msg_len)[0]
msg = conn.recv(dic_len).decode('utf-8')
msg = json.loads(msg)
return msg def download(conn):
g = os.walk(r'D:\python22\day30\下载文件')
file_lst = next(g)[2] # ['11.jpg', '23.mp4', 'userinfo']
my_send(conn,file_lst) #将文件列表发送到客户端 while 1:
num = conn.recv(1024).decode('utf-8') # 选择要下载文件的序号
if num.upper() == 'Q':break
else:
path = r'D:\python22\day30\下载文件'
abs_path = os.path.join(path,file_lst[int(num) - 1])
filename = os.path.basename(abs_path)
filesize = os.path.getsize(abs_path)
dic = {'filename': filename, 'filesize': filesize}
my_send(conn,dic) #发送用户选择要下载文件的信息,是一个字典 with open(abs_path, mode='rb') as f:
while filesize > 0:
content = f.read(1024)
filesize -= len(content)
conn.send(content) def upload(conn):
while 1:
msg = my_recv(conn)
if msg['filename'] == None:break
else:
with open(msg['filename'],'wb') as f:
while msg['filesize'] > 0:
content = conn.recv(1024)
msg['filesize'] -= len(content)
f.write(content)
conn.send('上传成功'.encode('utf-8')) def get_md5(username,password):
md5 = hashlib.md5(username.encode('utf-8'))
md5.update(password.encode('utf-8'))
return md5.hexdigest() def login(conn):
flag = True#用于跳出外层循环
while flag: #注意跳出多级循环问题
msg = my_recv(conn)
with open('userinfo') as f:
for line in f:
name, pwd = line.strip().split('|')
if name == msg['username'] and pwd == get_md5(name, msg['password']):
res, flag = True, False
break #跳出本级循环
else:
res = False
dic = {'operate': 'login', 'result': res} #状态码
my_send(conn, dic) #主逻辑
sk = socket.socket()
sk.bind(('127.0.0.1',9002))
sk.listen() conn,_ =sk.accept()
login(conn)
opt_dic = my_recv(conn)
if hasattr(sys.modules[__name__],opt_dic['operate']): # __name__是变量名,以脚本运行时,对应的值为'__main__'。但是被当做模块导入时,名字为模块名。所以最好用__name__
getattr(sys.modules[__name__],opt_dic['operate'])(conn) conn.close()
sk.close() #client
import os
import sys
import json
import struct
import socket
def download(sk): # 下载
opt_dic = {'operate':'download'}
my_send(sk,opt_dic) #将要进行的操作发送到服务端 file_lst = my_recv(sk) #接收到来自服务端的文件列表
while 1:
for index, file in enumerate(file_lst, 1):
print(index,file)
num = input('请输入要下载文件的序号(退出请按Q):').strip()
if num.upper() == 'Q':
sk.send(num.encode('utf-8')) # 发送q或Q
break
elif num.isdigit() and 0 < int(num) <= len(file_lst):
sk.send(num.encode('utf-8')) # 发送要下载文件的序号
msg = my_recv(sk) #接收要下载文件的信息,是一个字典
with open(msg['filename'], 'wb') as f:
while msg['filesize'] > 0:
content = sk.recv(1024)
msg['filesize'] -= len(content)
f.write(content)
print('下载成功')
else:
print('输入有误') def upload(sk):
opt_dic = {'operate': 'upload'}
my_send(sk, opt_dic) g = os.walk(r'D:\python22\day30\上传文件')
file_lst = next(g)[2] # ['11.jpg', '23.mp4', 'userinfo']
while 1:
for index, file in enumerate(file_lst, 1):
print(index, file)
num = input('请输入要上传文件的序号(退出请按Q):').strip()
if num.upper() == 'Q':
dic = {'filename': None, 'filesize': None}
my_send(sk, dic)
break
elif num.isdigit() and 0 < int(num) <= len(file_lst):
path = r'D:\python22\day30\上传文件'
abs_path = os.path.join(path, file_lst[int(num) - 1])
filename = os.path.basename(abs_path)
filesize = os.path.getsize(abs_path)
dic = {'filename': filename, 'filesize': filesize}
my_send(sk,dic) with open(abs_path, mode='rb') as f:
while filesize > 0:
content = f.read(1024)
filesize -= len(content)
sk.send(content)
msg = sk.recv(1024).decode('utf-8')
print(msg) def my_recv(sk): # 接收
msg_len = sk.recv(4)
dic_len = struct.unpack('i', msg_len)[0]
msg = sk.recv(dic_len).decode('utf-8')
msg = json.loads(msg)
return msg def my_send(sk,dic): # 发送
str_dic = json.dumps(dic)
b_dic = str_dic.encode('utf-8')
mlen = struct.pack('i', len(b_dic))
sk.send(mlen) # 4个字节 表示字典转成字节之后的长度
sk.send(b_dic) # 具体的字典数据 def login(sk):
while True: #alex|aee949757a2e698417463d47acac93df
usr = input('用户名:').strip() #alex
pwd = input('密 码 :').strip() #3714
dic = {'username': usr, 'password': pwd}
my_send(sk, dic)
ret = my_recv(sk) #dic = {'operate': 'login', 'result': res} res=True 或 False
if ret['operate'] == 'login' and ret['result']:
print('登录成功')
break
else:
print('登录失败') #主逻辑
sk = socket.socket()
sk.connect(('127.0.0.1',9002)) login(sk) # 登录
opt_lst = ['upload','download']
for index,opt in enumerate(opt_lst,1):
print(index,opt)
num = int(input('请选择您要操作的序号 :'))
getattr(sys.modules[__name__],opt_lst[num-1])(sk) sk.close()

基于tcp协议的登录,文件上传和下载的更多相关文章

  1. 网络编程应用:基于TCP协议【实现文件上传】--练习

    要求: 基于TCP协议实现一个向服务器端上传文件的功能 客户端代码: package Homework2; import java.io.File; import java.io.FileInputS ...

  2. 转:【专题十一】实现一个基于FTP协议的程序——文件上传下载器

    引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...

  3. 专题十一:实现一个基于FTP协议的程序——文件上传下载器

    引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...

  4. 实现一个基于FTP协议的程序——文件上传下载器(十三)

    此为一个系列,后续会把内容补上...

  5. koa2基于stream(流)进行文件上传和下载

    阅读目录 一:上传文件(包括单个文件或多个文件上传) 二:下载文件 回到顶部 一:上传文件(包括单个文件或多个文件上传) 在之前一篇文章,我们了解到nodejs中的流的概念,也了解到了使用流的优点,具 ...

  6. 基于 Django的Ajax实现 文件上传

    ---------------------------------------------------------------遇到困难的时候,勇敢一点,找同学朋友帮忙,找导师求助. Ajax Ajax ...

  7. Resumable.js – 基于 HTML5 File API 的文件上传

    Resumable.js 是一个 JavaScript 库,通过 HTML5 文件 API 提供,稳定和可恢复的批量上传功能.在上传大文件的时候通过每个文件分割成小块,每块在上传失败的时候,上传会不断 ...

  8. 基于jsp的文件上传和下载

    参考: 一.JavaWeb学习总结(五十)--文件上传和下载 此文极好,不过有几点要注意: 1.直接按照作者的代码极有可能listfile.jsp文件中 <%@taglib prefix=&qu ...

  9. 基于hap的文件上传和下载

    序言 现在,绝大部分的应用程序在很多的情况下都需要使用到文件上传与下载的功能,在本文中结合hap利用spirng mvc实现文件的上传和下载,包括上传下载图片.上传下载文档.前端所使用的技术不限,本文 ...

随机推荐

  1. 谷歌推出全新Android开发语言Sky:让App更流畅

    土豆网同步更新:http://www.tudou.com/plcover/VHNh6ZopQ4E/   使用HTML 创建Mac OS App 视频教程. 官方QQ群: (1)App实践出真知 434 ...

  2. Python正则表达式基础指南

    1. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十 ...

  3. UISearchController 的大坑

         UISearchBar+UISearchDisplayController这个组合的稳定性经过几次iOS版本迭代肯定不言而喻,但苹果爸爸就是任性的在iOS8.0中宣布弃用UISearchDi ...

  4. Spring Cloud微服务简介

    概述 Spring Cloud给开发者提供一套按照一定套路快速开发分布式工具.它为微服务架构中涉及**配置管理,服务治理,断路器,智能路由,微代理,控制总线,全局锁,分布式会话和集群状态等操作提供了一 ...

  5. .NET开发框架(二)-框架功能简述

    若视频播放不了,请点击 这里查看 本框架为响应式SPA框架,支持PC与手机端的屏幕自适应.手机展示效果视频在文章末尾查看. 框架入口地址:http://letyouknow.net/ 1.框架登录界面 ...

  6. 纯CSS制作加<div>制作动画版哆啦A梦

    纯CSS代码加上<div>制作动画版哆啦A梦(机器猫) 哆啦A梦(机器猫)我们大家一定都很熟悉,今天给大家演示怎么用纯CSS代码,来做一个动画版的哆啦A梦. 效果图: ###下面代码同学可 ...

  7. tomcat实现

    转载地址:https://blog.csdn.net/u014795347/article/details/52328221?locationNum=2&fps=1 以下代码纯属本人复制,而且 ...

  8. laravel中的构造函数依赖注入理解

    laravel中的自动依赖注入是非常强大的,刚开始会疑惑为什么只要在构造函数中传入一个强制类型的变量(就是参数有类型限制)过去就行了? 通过查看源码即查阅资料发现其实这其中有一个php技术,就是反射技 ...

  9. Jenkins+Python+GitLab持续集成

    创建任务 登录Jenkins,点击左侧列表的新建选项.输入任务名称,选择构建一个自由风格的软件项目,点击确定. 配置 在任务配置界面,可以设置General标签中的丢弃旧的构建选项,设置保持构建的天数 ...

  10. 开源系统监控工具Nagios、Zabbix和Open-Falcon的功能特性汇总及优缺点比较

    Nagios Nagios 全名为(Nagios Ain’t Goona Insist on Saintood),最初项目名字是 NetSaint.它是一款免费的开源 IT 基础设施监控系统,其功能强 ...