client.py
import os
import sys
import json
import struct
import socket # 下载--接收文件
def download(sk): # 下载
opt_dic = {'operate':'download'}
my_send(sk,opt_dic)
msg = my_recv(sk)
with open(msg['filename'], 'wb') as f:
print('File is downloading...')
while msg['filesize'] > 0:
content = sk.recv(1024)
msg['filesize'] -= len(content)
f.write(content)
print('File download finished...') # 上传--传送文件
def upload(sk):
opt_dic = {'operate':'upload'}
my_send(sk,opt_dic)
path_list=my_recv(sk)['upload_path']
for index, path in enumerate(path_list,1):
print(index, path)
selected_path = input('请输入目的文件夹的序号:')
uploaded_file = input('请输入本地要上传的文件的全路径:')
filename = os.path.basename(uploaded_file)
filesize = os.path.getsize(uploaded_file)
dic = {'uploaded_path': selected_path, 'filename': filename, 'filesize': filesize}
my_send(sk,dic) with open(uploaded_file, mode='rb') as f:
print('File is uploading...')
while filesize > 0:
content = f.read(1024)
filesize -= len(content)
sk.send(content)
print('File upload finished') # 登录
def login(sk):
while True:
usr = input('用户名:').strip()
pwd = input('密 码 :').strip()
dic = {'username': usr, 'password': pwd} # 将用户名和密码放在字典里发过去,而不是单独发送。
my_send(sk, dic)
ret = my_recv(sk)
if ret['operate'] == 'login' and ret['result']:
print('登录成功')
break
else:
print('登录失败') # 将 sk.recv(num)封装到函数里:
# 1-提高复用度;2-每次都使用 struct防止粘包 3;将 server,client实现某一功能的代码对应起来(如,两边都有 download())
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 # 将 sk.send(msg)封装到函数里:
# 1-提高复用度;2-每次都使用 struct防止粘包 3;将 server,client实现某一功能的代码对应起来(如,两边都有 download())
def my_send(sk,dic): # 发送 {'username': usr, 'password': pwd} 或者 {'operate':'download'}
str_dic = json.dumps(dic) # 网络通信中 一般使用 json而非 pickle
b_dic = str_dic.encode('utf-8') # 将 json字符串 encode成 字节串
mlen = struct.pack('i', len(b_dic))
sk.send(mlen) # 4个字节 表示字典转成字节之后的长度
sk.send(b_dic) # 具体的字典数据 def exit(sk):
# sys.exit()
global flag
flag = False
opt_dic = {'operate': 'exit'}
my_send(sk,opt_dic)
# sk.close() if __name__ == '__main__': sk = socket.socket()
# sk.connect(('192.168.14.109',9012))
sk.connect(('127.0.0.1',9001)) login(sk) # 登录
# 上传\下载
flag=True
while flag:
opt_lst = ['upload','download','exit']
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()
# sk.close()
server.py (socket版)
import os
import sys
import json
import struct
import socket
import hashlib # 将 conn.send(msg)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包
def my_send(conn,dic):
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) # 具体的字典数据 # download--发送文件
def download(conn):
abs_path = r'C:\Users\12078\PycharmProjects\OldBoy\Day32\登陆验证文件下载_完整版\视频文件源位置\测试视频.mp4'
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):
upload_path = ['upload_path1', 'upload_path2']
my_send(conn,{'upload_path':upload_path})
file_dic=my_recv(conn)
file_path = upload_path[int(file_dic['uploaded_path']) - 1] + '\\' + file_dic['filename']
with open(file_path, 'wb') as f:
while file_dic['filesize'] > 0:
content = conn.recv(1024)
file_dic['filesize'] -= len(content)
f.write(content) # 将 conn.recv(num)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包
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) # 网网络通信中使用较多的是json而不是pickle
return msg # 将密码进行加密,使用username作为 salt
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) # 接收到的是 dic = {'username': usr, 'password': pwd}
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) # 将登录结果发送给 client def exit(conn):
# sys.exit()
# sk.close()
global flag
flag = False
conn.close() # 只断开和客户端的连接,不关闭服务。 if __name__ == '__main__': sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen() while True: # 允许和多个客户端连接(非并行)
conn,_ =sk.accept()
# 有了一个客户端来连接你
login(conn) flag = True
while flag:
# 接收消息,根据用户的选择进行上传/下载操作
opt_dic = my_recv(conn) # {'operate':'download'} 或 {'operate':'upload'}
if hasattr(sys.modules[__name__],opt_dic['operate']):
getattr(sys.modules[__name__],opt_dic['operate'])(conn) # conn.close()
sk.close()
server.py(socketserver版)
import os
import sys
import json
import struct
import hashlib
import socketserver class Myserver(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
login(conn)
flag = True
while flag: # 不需要更外层的那个 while了,和多个客户端通讯的任务交给了socketserver.
try:
# 接收消息,根据用户的选择进行上传/下载操作
opt_dic = my_recv(conn) # {'operate':'download'} 或 {'operate':'upload'} ,{'operate':'exit'}
if hasattr(sys.modules[__name__], opt_dic['operate']):
getattr(sys.modules[__name__], opt_dic['operate'])(conn)
if opt_dic['operate']=='exit': flag=False # 这样做判断,虽然破坏了 反射的简介,但【只有这样】才能退出连接。
except ConnectionResetError: # 处理异常断开连接,比如客户端非正常退出。
break
conn.close() # 只断开和客户端的连接,不关闭服务。 # 将 conn.send(msg)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包; 3-每次 send/recv都struct一下。
def my_send(conn,dic):
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) # 具体的字典数据 # download--发送文件
def download(conn):
abs_path = r'C:\Users\12078\PycharmProjects\OldBoy\Day32\登陆验证文件下载_完整版\视频文件源位置\测试视频.mp4'
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):
upload_path = ['upload_path1', 'upload_path2']
my_send(conn,{'upload_path':upload_path})
file_dic=my_recv(conn)
file_path = upload_path[int(file_dic['uploaded_path']) - 1] + '\\' + file_dic['filename']
with open(file_path, 'wb') as f:
while file_dic['filesize'] > 0:
content = conn.recv(1024)
file_dic['filesize'] -= len(content)
f.write(content) # 将 conn.recv(num)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包; 3-每次 send/recv都struct一下。
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) # 网网络通信中使用较多的是json而不是pickle
return msg # 将密码进行加密,使用username作为 salt
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) # 接收到的是 dic = {'username': usr, 'password': pwd}
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) # 将登录结果发送给 client def exit(conn):
# sys.exit()
# sk.close()
# global flag
# flag = False
conn.close() # 只断开和客户端的连接,不关闭服务。 if __name__ == '__main__':
flag = True
server = socketserver.ThreadingTCPServer(('127.0.0.1', 9001), Myserver)
server.serve_forever()

最新文章

  1. Django 后台管理设置(admin.py)
  2. java工程或web工程项目上出现红色感叹号
  3. window.location和window.open
  4. 用纯原生js实现jquery的ready函数(两种实现)
  5. Linux源代码情景分析读书笔记 物理页面的分配
  6. VB.NET开发中遇到的一点小问题
  7. 关于Json传递的日期/Date(数字)/解析
  8. mount 挂载光盘
  9. Android Studio tips and tricks 翻译学习
  10. [51daifan]来吧,一起书写51daifan的成长史吧-让一部分人先安全起来
  11. centOS7配置DNS服务器
  12. ftp:connect:未知错误号
  13. CDI services--Event(事件)
  14. 第二节,神经网络中反向传播四个基本公式证明——BackPropagation
  15. 全面接触PDF:最好用的PDF软件汇总(转)
  16. Confluence 6 编辑一个站点装饰文件
  17. asp.net通过后台代码给前台设置css样式,下拉列表在js中的取值
  18. 前端 html css
  19. Android - Resource 之 Layout 小结
  20. Sona

热门文章

  1. 技术心得丨一种有效攻击BERT等模型的方法
  2. 多测师讲解selenium_iframe框定位_高级讲师肖sir
  3. 如何修改或新增visual studio 的模板
  4. day43 Pyhton 并发编程06
  5. Mysql索引(一篇就够le)
  6. Thumbnailator处理图片
  7. beego log
  8. centos8平台使用ab做压力测试
  9. <bdi> 标签
  10. count=count++