17 [网络编程]-文件传输
1.通过socket收发文件软件开发
1、客户端提交命令 2、服务端接收命令,解析,执行下载文件的方法,即以读的方式打开文件,for循环读出文件的一行行内容,然后send给客户端 3、客户端以写的方式打开文件,将接收的内容写入文件中
2、文件传输普通版
(1)服务端
import socket import struct import subprocess import json import os server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('127.0.0.1', 9994)) server.listen(5) while True: print('waiting...') conn, addr = server.accept() while True: try: cmds = conn.recv(1024) # get a.txt print('=》', cmds) if not cmds: break # 提取出相应的命令参数 filename = cmds.decode('utf-8').split()[1] print(filename) # 以读的方式打开文件,将数据一点点发送给客户端 # 第一步:制作报头 header_dict = { 'filename': filename, 'md5': 'afdsafsaf', 'total_size': os.path.getsize(filename) } header_json = json.dumps(header_dict) # 报头的json样式 header_bytes = header_json.encode('utf-8') # 报头---报头.json---报头.bytes # 发送报头的长度 header_len = struct.pack('i', len(header_bytes)) # 报头bytes---> len()---> struct conn.send(header_len) # 第二部:把报头发送给客户端 conn.send(header_bytes) # 第三部:发送真实数据 with open(filename, 'rb') as f: for line in f: conn.send(line) except ConnectionResetError: break conn.close() server.close()
(2)客户端
import socket import struct import json client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('127.0.0.1', 9994)) while True: data = input('>>>').strip() # get a.txt if not data: continue client.send(data.encode('utf-8')) # 以写的方式,打开一个新文件,接受服务端传来的文件内容,写入新文件 # 2.接受报头的长度 header_bytes_len = client.recv(1024) header_bytes_len = struct.unpack('i', header_bytes_len)[0] # 接收报头的json数据 header_bytes = client.recv(header_bytes_len) print(header_bytes) # 3.从报头中解析出对真实数据的描述信息(数据的长度) header_json = header_bytes.decode('utf-8') header_dict = json.loads(header_json) total_size = header_dict['total_size'] filename = header_dict['filename'] # 3.一段段的取数据 # 4.打开文件,写入内容 new_file = "%s.bak" % filename with open(new_file, 'wb') as f: recv_size = 0 while recv_size < total_size: # 接受的数据长度 = len(total_data) 已经取完了,就退出 data = client.recv(1024) f.write(data) recv_size += len(data) client.close()
3、文件传输:拼接路径版本
import socket import struct import subprocess import json import os server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('127.0.0.1', 9994)) server.listen(5) while True: print('waiting...') conn, addr = server.accept() while True: try: cmds = conn.recv(1024) # get a.txt print('=》', cmds) if not cmds: break # 提取出相应的命令参数 filename = cmds.decode('utf-8').split()[1] # 获取basename print(filename) # 绝对路径拼接 SERVER_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(SERVER_PATH, 'share'), filename) # 以读的方式打开文件,将数据一点点发送给客户端 # 第一步:制作报头 header_dict = { 'filename': FILE_PATH, 'md5': 'afdsafsaf', 'total_size': os.path.getsize(FILE_PATH) } header_json = json.dumps(header_dict) # 报头的json样式 header_bytes = header_json.encode('utf-8') # 报头---报头.json---报头.bytes # 发送报头的长度 header_len = struct.pack('i', len(header_bytes)) # 报头bytes---> len()---> struct conn.send(header_len) # 第二部:把报头发送给客户端 conn.send(header_bytes) # 第三部:发送真实数据 with open(FILE_PATH, 'rb') as f: for line in f: conn.send(line) except ConnectionResetError: break conn.close() server.close()
import socket import os import struct import json client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('127.0.0.1', 9994)) while True: data = input('>>>').strip() # get a.txt if not data: continue client.send(data.encode('utf-8')) # 以写的方式,打开一个新文件,接受服务端传来的文件内容,写入新文件 # 2.接受报头的长度 header_bytes_len = client.recv(1024) header_bytes_len = struct.unpack('i', header_bytes_len)[0] # 接收报头的json数据 header_bytes = client.recv(header_bytes_len) # 3.从报头中解析出对真实数据的描述信息(数据的长度) header_json = header_bytes.decode('utf-8') header_dict = json.loads(header_json) total_size = header_dict['total_size'] filename = header_dict['filename'] # 3.一段段的取数据 # 4.打开文件,写入内容, 文件路径修改 CLIENT_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), os.path.basename(filename)) with open(FILE_PATH, 'wb') as f: recv_size = 0 while recv_size < total_size: # 接受的数据长度 = len(total_data) 已经取完了,就退出 data = client.recv(1024) f.write(data) recv_size += len(data) print("总共%s bytes 已经传输%s bytes" %(total_size,recv_size)) # 简易进度条 client.close()
- pycharm 显示目录延迟!
4、函数版本:上传,下载功能
(1)服务端
import socket import struct import subprocess import json import os def get(cmds, conn): filename = cmds.decode('utf-8').split()[1] # 获取basename # 绝对路径拼接 SERVER_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(SERVER_PATH, 'share'), filename) # 以读的方式打开文件,将数据一点点发送给客户端 # 第一步:制作报头 header_dict = { 'filename': FILE_PATH, 'md5': 'afdsafsaf', 'total_size': os.path.getsize(FILE_PATH) } header_json = json.dumps(header_dict) # 报头的json样式 header_bytes = header_json.encode('utf-8') # 报头---报头.json---报头.bytes # 发送报头的长度 header_len = struct.pack('i', len(header_bytes)) # 报头bytes---> len()---> struct conn.send(header_len) # 第二部:把报头发送给客户端 conn.send(header_bytes) # 第三部:发送真实数据 with open(FILE_PATH, 'rb') as f: for line in f: conn.send(line) def put(client): # 2.接受报头的长度 header_bytes_len = client.recv(1024) header_bytes_len = struct.unpack('i', header_bytes_len)[0] # 接收报头的json数据 header_bytes = client.recv(header_bytes_len) # 3.从报头中解析出对真实数据的描述信息(数据的长度) header_json = header_bytes.decode('utf-8') header_dict = json.loads(header_json) total_size = header_dict['total_size'] filename = header_dict['filename'] # 3.一段段的取数据 # 4.打开文件,写入内容, 文件路径修改 CLIENT_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'share'), os.path.basename(filename)) with open(FILE_PATH, 'wb') as f: recv_size = 0 while recv_size < total_size: # 接受的数据长度 = len(total_data) 已经取完了,就退出 data = client.recv(1024) f.write(data) recv_size += len(data) print("总共%s bytes 已经传输%s bytes" % (total_size, recv_size)) # 简易进度条 def main(): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('127.0.0.1', 9994)) server.listen(5) while True: print('waiting...') conn, addr = server.accept() while True: try: cmds = conn.recv(1024) # get a.txt print('=》', cmds) if not cmds: break # 提取出相应的命令参数 cmd_type = cmds.decode('utf-8').split()[0] if cmd_type == 'get': get(cmds, conn) elif cmd_type == 'put': put(conn) except ConnectionResetError: break conn.close() server.close() if __name__ == '__main__': main()
(2)客户端
import socket import os import struct import json def get(client): # 以写的方式,打开一个新文件,接受服务端传来的文件内容,写入新文件 # 2.接受报头的长度 header_bytes_len = client.recv(1024) header_bytes_len = struct.unpack('i', header_bytes_len)[0] # 接收报头的json数据 header_bytes = client.recv(header_bytes_len) # 3.从报头中解析出对真实数据的描述信息(数据的长度) header_json = header_bytes.decode('utf-8') header_dict = json.loads(header_json) total_size = header_dict['total_size'] filename = header_dict['filename'] # 3.一段段的取数据 # 4.打开文件,写入内容, 文件路径修改 CLIENT_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), os.path.basename(filename)) with open(FILE_PATH, 'wb') as f: recv_size = 0 while recv_size < total_size: # 接受的数据长度 = len(total_data) 已经取完了,就退出 data = client.recv(1024) f.write(data) recv_size += len(data) print("总共%s bytes 已经传输%s bytes" % (total_size, recv_size)) # 简易进度条 def put(cmds,client): # 文件路径拼接 filename = cmds.split()[1] # 获取basename CLIENT_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), filename) if not os.path.isfile(FILE_PATH): print('this file is not find') return # 1.找出file的绝对路径 # 2.读取文件的size header_dict = { 'filename': FILE_PATH, 'md5': 'dffsaf', 'total_size': os.path.getsize(FILE_PATH), } # 3.传输报头 header_json = json.dumps(header_dict) header_bytes = header_json.encode('utf-8') header_len = struct.pack('i', len(header_bytes)) client.send(header_len) client.send(header_bytes) # 4.打开文件读取内容,并传输 with open(FILE_PATH, 'rb') as f: for line in f: client.send(line) def main(): client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('127.0.0.1', 9994)) while True: cmds = input('>>>').strip() if not cmds: continue client.send(cmds.encode('utf-8')) cmd_type = cmds.split()[0] if cmd_type == 'get': get(client) elif cmd_type == 'put': put(cmds,client) client.close() if __name__ == '__main__': main()
5、面向对象,类:文件传输
- 自己写的
import socket import struct import subprocess import json import os class Server(object): def __init__(self,ip,port): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.ip = ip self.port = port def run(self): self.bind() self.listen() while True: print('waiting...') conn, addr = self.accept() print(conn, addr) while True: try: cmds = self.recv(conn) print('=》', cmds) if not cmds: break self.get(cmds, conn) except ConnectionResetError: break conn.close() self.socket.close() def bind(self): self.socket.bind((self.ip, self.port)) def listen(self,): self.socket.listen(5) def accept(self): conn, addr = self.socket.accept() return conn, addr def recv(self,conn): cmds = conn.recv(1024) return cmds def get(self,cmds, conn): filename = cmds.decode('utf-8').split()[1] SERVER_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(SERVER_PATH, 'share'), filename) header_dict = { 'filename': FILE_PATH, 'md5': 'afdsafsaf', 'total_size': os.path.getsize(FILE_PATH) } header_json = json.dumps(header_dict) header_bytes = header_json.encode('utf-8') header_len = struct.pack('i', len(header_bytes)) conn.send(header_len) conn.send(header_bytes) with open(FILE_PATH, 'rb') as f: for line in f: conn.send(line) server = Server('127.0.0.1', 9994) server.run()
import socket import os import struct import json class Client(object): def __init__(self,ip,port): self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.ip = ip self.port = port def run(self): self.connect() while True: data = input('>>>').strip() if not data: continue self.client.send(data.encode('utf-8')) self.get() self.client.close() def connect(self): self.client.connect((self.ip, self.port)) def get(self): header_bytes_len = self.client.recv(1024) header_bytes_len = struct.unpack('i', header_bytes_len)[0] header_bytes = self.client.recv(header_bytes_len) header_json = header_bytes.decode('utf-8') header_dict = json.loads(header_json) total_size = header_dict['total_size'] filename = header_dict['filename'] CLIENT_PATH = os.path.dirname(os.path.abspath(__file__)) FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), os.path.basename(filename)) with open(FILE_PATH, 'wb') as f: recv_size = 0 while recv_size < total_size: # 接受的数据长度 = len(total_data) 已经取完了,就退出 data = self.client.recv(1024) f.write(data) recv_size += len(data) print("总共%s bytes 已经传输%s bytes" % (total_size, recv_size)) # 简易进度条 client = Client('127.0.0.1',9994) client.run()
- 老师写的
import socket import struct import json import subprocess import os class MYTCPServer: address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding='utf-8' request_queue_size = 5 server_dir='file_upload' def __init__(self, server_address, bind_and_activate=True): """Constructor. May be extended, do not override.""" self.server_address=server_address self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_activate: try: self.server_bind() self.server_activate() except: self.server_close() raise def server_bind(self): """Called by constructor to bind the socket. """ if self.allow_reuse_address: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) self.server_address = self.socket.getsockname() def server_activate(self): """Called by constructor to activate the server. """ self.socket.listen(self.request_queue_size) def server_close(self): """Called to clean-up the server. """ self.socket.close() def get_request(self): """Get the request and client address from the socket. """ return self.socket.accept() def close_request(self, request): """Called to clean up an individual request.""" request.close() def run(self): while True: self.conn,self.client_addr=self.get_request() print('from client ',self.client_addr) while True: try: head_struct = self.conn.recv(4) if not head_struct:break head_len = struct.unpack('i', head_struct)[0] head_json = self.conn.recv(head_len).decode(self.coding) head_dic = json.loads(head_json) print(head_dic) #head_dic={'cmd':'put','filename':'a.txt','filesize':123123} cmd=head_dic['cmd'] if hasattr(self,cmd): func=getattr(self,cmd) func(head_dic) except Exception: break def put(self,args): file_path=os.path.normpath(os.path.join( self.server_dir, args['filename'] )) filesize=args['filesize'] recv_size=0 print('----->',file_path) with open(file_path,'wb') as f: while recv_size < filesize: recv_data=self.conn.recv(self.max_packet_size) f.write(recv_data) recv_size+=len(recv_data) print('recvsize:%s filesize:%s' %(recv_size,filesize)) tcpserver1=MYTCPServer(('127.0.0.1',8080)) tcpserver1.run()
import socket import struct import json import os class MYTCPClient: address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding='utf-8' request_queue_size = 5 def __init__(self, server_address, connect=True): self.server_address=server_address self.socket = socket.socket(self.address_family, self.socket_type) if connect: try: self.client_connect() except: self.client_close() raise def client_connect(self): self.socket.connect(self.server_address) def client_close(self): self.socket.close() def run(self): while True: inp=input(">>: ").strip() if not inp:continue l=inp.split() cmd=l[0] if hasattr(self,cmd): func=getattr(self,cmd) func(l) def put(self,args): cmd=args[0] filename=args[1] if not os.path.isfile(filename): print('file:%s is not exists' %filename) return else: filesize=os.path.getsize(filename) head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize} print(head_dic) head_json=json.dumps(head_dic) head_json_bytes=bytes(head_json,encoding=self.coding) head_struct=struct.pack('i',len(head_json_bytes)) self.socket.send(head_struct) self.socket.send(head_json_bytes) send_size=0 with open(filename,'rb') as f: for line in f: self.socket.send(line) send_size+=len(line) print(send_size) else: print('upload successful') client=MYTCPClient(('127.0.0.1',8080)) client.run()