day8-socket实现文件发送
简述
客户端发送指令到服务端要下载文件,这时候服务器在发送文件给客户端之前的检查步骤有哪些?
服务器端检查流程
代码实现
服务器端
思路:解析命令=>检测文件是否存在=>打开文件=>检测文件大小=>发送文件大小给客户端=>等待客户端的确认信息=>开始边读边发
import socket,os,hashlib server = socket.socket() server.bind(("localhost",9972)) server.listen() while True: conn,addr = server.accept() print("new conn:",addr) while True: data = conn.recv(1024) if not data: print("客户端已断开") break cmd,filename = data.decode().split() #接收客户端发过来的命令和文件名 print(filename) if os.path.isfile(filename): #判断文件是否存在 with open(filename,"rb") as f1: file_total_size = os.stat(filename).st_size #获取文件大小 conn.send(str(file_total_size).encode()) #发送文件大小给客户端 conn.recv(1024) #接收客户端的ack信息 for line in f1: conn.send(line) #边读边发文件给客户端 f1.close() print("发送完成!") server.close() #运行输出 new conn: ('127.0.0.1', 62469) t_test.py
客户端
思路:判断命令是否是下载动作=>发送命令给服务器端=>接收文件大小=>发送确认信息给客户端=>打开空文件=>循环接收文件并写入空文件
import socket client = socket.socket() client.connect(("localhost",9971)) while True: cmd_input = input(">>:") if len(cmd_input) == 0: continue if cmd_input.startswith("get"): client.send(cmd_input.encode()) #发送命令给服务器端 server_response = client.recv(1024) #接收文件大小 print("server response:",server_response) client.send("准备接收文件".encode()) #发送确认信息给服务器端 file_total_size = int(server_response.decode()) recv_size = 0 #初始化文件大小为0 filename = cmd_input.split()[1] #获取文件名 with open(filename+".new","wb") as f1: while recv_size < file_total_size: #判断接收文件大小和文件总大小 data = client.recv(1024) recv_size+=len(data) #累加每次循环接收文件的大小 f1.write(data) #循环写入文件 print(file_total_size,recv_size) else: print("文件接收完成") f1.close() client.close() #运行输出 >>:get t_test.py server response: b'513' 513 475 513 513 文件接收完成 >>:
MD5值校验功能
我们在进行文件的下载时,为了保证文件的一致性,通常选择对文件做MD5的校验。
服务器端
思路:生成MD5对象=>对发送的数据计算MD5值=>生成16进制形式=>编码后发送给客户端
#运行输出 new conn: ('127.0.0.1', 62808) socket_server_ssh.py file MD5: 7e121fe6f7fbdd4dc4097a2e02744688
客户端
思路: 生成MD5对象=>对客户端接收的数据计算MD5值=>生成16进制形式=>接收服务端发来的原文件的MD5(16进制形式)=>判断接收的和服务器端发来的MD5是否相同
#运行输出 >>:get socket_server_ssh.py server response: b'836' 836 22 836 215 836 341 836 549 836 723 836 804 836 836 文件接收完成 server file MD5: 7e121fe6f7fbdd4dc4097a2e02744688 client file MD5: 7e121fe6f7fbdd4dc4097a2e02744688 文件校验成功! >>:
解析:程序实现了下载文件时对MD5进行校验的功能,但是由于服务端在#1和#2处存在2次连续的send,在测试运行中服务器端还是可能会出现粘包的问题,那么客户端也还是会接收服务器端发来的数据(包含文件数据和MD5),这就会造成文件下载错误,所以需要加入交互以解决粘包的问题。那么除了增加sleep和交互,还有别的方法解决粘包的问题吗?