对socket有基本了解后,写了一个简单的文件下载程序
服务端
import socket,os,hashlib
server = socket.socket()
server.bind(('0.0.0.0',9999))
# 监听socket
server.listen()
while True:
# 接收客户端消息
conn,addr = server.accept()
print('new conn:',addr)
while True:
print('等待新指令')
data = conn.recv(1024)
# 判断数据是否为空
if not data:
print('客户端已断开!')
break
cmd,filename = data.decode().split()
print(filename)
if os.path.isfile(filename):
f = open(filename,'rb')
m = hashlib.md5()
file_size = os.stat(filename).st_size
conn.send(str(file_size).encode()) #send file size
conn.recv(1024) #wait for ack
for line in f:
m.update(line)
conn.send(line)#可能会与后面的md5粘包,在client处理
print('file md5',m.hexdigest())
f.close()
conn.send(m.hexdigest().encode())
print('send done!')
server.close()
客户端
import socket
import hashlib
client = socket.socket()
client.connect(('localhost',9999))
while True:
cmd = input('>>:').strip()
if len(cmd)==0:continue
# 使用get命令
if cmd.startswith('get'):
client.send(cmd.encode('utf-8'))
# 接收服务器文件大小
file_size = client.recv(1024)
print('server_resonse',file_size)
client.send(b'ready to recv file')
file_total_size = int(file_size.decode())
received_size = 0
filename = cmd.split()[1]
f = open(filename+'.new','wb')
m=hashlib.md5()
while received_size < file_total_size: # 防止粘包,若数据为1025,则剩下的1可能会与md5一起发>送到client,导致md5写入到文件中。
if file_total_size - received_size > 1024:
size = 1024
else:
size = file_total_size - received_size
data = client.recv(size)
received_size += len(data)
m.update(data)
f.write(data)
# print(file_total_size,received_size)
else:
new_file_md5 = m.hexdigest()
print('file recv done',received_size,file_total_size)
f.close()
server_file_md5 = client.recv(1024)
print('server file md5',server_file_md5)
print('client file md5',new_file_md5 )
client.close()