前面两章记录了如何使用socket传输内存数据,下面就如何使用socket进行文件传输进行记录。下面代码实现了基础ftp功能,当前只实现了从client端使用“get filename”从客户端下载文件的功能,上传功能类似。其中对传输文件的md5值也进行了校验。
server端代码
1 # _*_ coding:utf-8 _*_ 2 import socket,os,hashlib 3 server = socket.socket() #创建连接描述符,默认使用iv4/tcp 4 server.bind(("localhost",6969)) #指定监听地址和端口,开始等待客户端连接。 5 server.listen(5) #监听 6 print("服务端已启动") 7 while True: 8 conn,addr = server.accept() #创建和客户端交互数据的连接 9 print('new conn',conn,addr) 10 while True: 11 type,filename = conn.recv(1024).decode().split() #1024为接收字节大小 12 print('get filename:',filename) 13 if len(filename) == 0: #判断客户端是否断开,若客户端断开则接收端接收的数据长度为0 14 print("client is close") 15 break 16 elif os.path.isfile(filename): #判断客户端发送的文件请求是否存在 17 f = open(filename,'rb') 18 m = hashlib.md5() 19 conn.send(str( os.stat(filename).st_size).encode(encoding='utf-8')) #发送文件大小 20 conn.recv(1024) 21 for line in f: 22 conn.send(line) 23 m.update(line) #对文件进行md5运算 24 print('file md5:',m.hexdigest()) 25 print( conn.recv(1024).decode()) 26 conn.send(m.hexdigest().encode(encoding='utf-8')) #发送文件的md5值 27 f.close() 28 else: 29 print('file is not exit') 30 conn.send(b'file is not exit') 31 continue 32 33 server.close() #关闭连接
client端代码
1 # _*_ coding:utf-8 _*_ 2 import socket,hashlib 3 client = socket.socket() #创建连接描述符,指定socket连接的网络层和传输层协议,默认使用ipv4/tcp 4 client.connect(("localhost",6969)) #使用连接描述符连接server,server信息以元组形式传入,包含ip地址和端口号 5 while True: 6 cmd = input("input your command,eg:get 'filename':") 7 if len(cmd) == 0: 8 continue 9 client.send(cmd.encode(encoding='utf-8')) #发送hello world,send只能发送byte类型,不能发送字符串。encode默认会将字符串转为byte类型 10 file_size_tmp = client.recv(1024).decode() #接收服务端发送的文件大小/服务器端返回文件不存在 11 if file_size_tmp == 'file is not exit': 12 continue 13 else: 14 file_size = int(file_size_tmp) 15 print("file_size is:",file_size) 16 recv_size = 0 17 client.send(b'i have receive file_size') #为解决粘包问题,给服务端发送响应 18 f = open(cmd.split()[1] + '_new','wb') 19 m = hashlib.md5() 20 while recv_size < file_size: #通过此循环持续收包 21 data=client.recv(1024) 22 f.write(data) 23 m.update(data) 24 recv_size += len(data) 25 print('recv_size:',recv_size) 26 client.send(b'Client have receive this file') 27 server_md5 = client.recv(1024).decode() 28 if server_md5 == m.hexdigest(): #校验接收和发送的文件md5值是否一样 29 print('this file get success') 30 else: 31 print('this file get faild,MD5 is not matched') 32 continue 33 34 client.close()