文件传送

简单版
服务端
import socket
import subprocess
import struct
import json
import os
share_dir = r'F:\project\book\chapter6\文件传输\简单版本\server\share'
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (如果机器中存在,重新用端口)应对端口占用报错情况
phone.bind(("127.0.0.1", 9909)) # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
phone.listen(5) # 5代表最大挂起连接数
print("starting...")
while True: # 循环链接
conn, client = phone.accept() # conn套接字对象
while True: # 通讯循环
try:
# 1、接收命令 (命令:执行系统命令)
res = conn.recv(8096) # b'get a.txt
# 2、解析命令,提取相应的命令参数
cmds = res.decode("utf-8").split()
filename = cmds[1]
# 3、以读的方式打开文件,读取文件内容,发送给客户端
# 第一步:制作固定长度的报头(import struct)
header_dic = {
"filename": filename,
"md5": "xxdxxx",
"file_size": os.path.getsize(r"%s/%s" % (share_dir, filename))
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode("utf-8")
# 第二步:先发送报头的长度
conn.send(struct.pack("i", len(header_bytes)))
# 第三步:再发报头
conn.send(header_bytes)
# 第四步:再发送真实的数据
with open("%s/%s" % (share_dir, filename), "rb")as f:
# conn.send(f.read()) # 如果文件太大,会占满内存
for line in f:
conn.send(line)
except ConnectionRefusedError:
break
conn.close()
phone.close()
客户端
import socket
import struct
import json
download_dir = r"F:\project\book\chapter6\文件传输\简单版本\client\download"
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(("127.0.0.1", 9909)) # phone相当于服务端的conn
while True:
# 1、发命令
cmd = input(">> ").strip() # get a.txt
if not cmd:
continue
phone.send(cmd.encode("utf-8"))
# 2、以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户端的新文件中
# 第一步:先收报头的长度
header = phone.recv(4)
header_size = struct.unpack("i", header)[0]
# 第二步:再接收报头信息
header_bytes = phone.recv(header_size)
# 第三步:从报头中解析出对真实数据的描述信息
header_json = header_bytes.decode("utf-8")
header_dic = json.loads(header_json)
print(header_dic)
file_size = header_dic["file_size"]
filename = header_dic["filename"]
# 第四步:接受真实的数据
with open("%s/%s" % (download_dir, filename), "wb")as f:
recv_size = 0
while recv_size < file_size:
line = phone.recv(1024)
f.write(line)
recv_size += len(line)
print("总大小:%s 已下载大小:%s" % (file_size, recv_size))
phone.close()
函数版
服务端
import socket
import subprocess
import struct
import json
import os
share_dir = r'F:\project\book\chapter6\文件传输\函数版本\server\share'
def get(conn, cmds):
filename = cmds[1]
# 3、以读的方式打开文件,读取文件内容,发送给客户端
# 第一步:制作固定长度的报头(import struct)
header_dic = {
"filename": filename,
"md5": "xxdxxx",
"file_size": os.path.getsize(r"%s/%s" % (share_dir, filename))
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode("utf-8")
# 第二步:先发送报头的长度
conn.send(struct.pack("i", len(header_bytes)))
# 第三步:再发报头
conn.send(header_bytes)
# 第四步:再发送真实的数据
with open("%s/%s" % (share_dir, filename), "rb")as f:
# conn.send(f.read()) # 如果文件太大,会占满内存
for line in f:
conn.send(line)
def put(conn, cmds):
pass
def run():
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (如果机器中存在,重新用端口)应对端口占用报错情况
phone.bind(("127.0.0.1", 9909)) # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
phone.listen(5) # 5代表最大挂起连接数
print("starting...")
while True: # 循环链接
conn, client = phone.accept() # conn套接字对象
while True: # 通讯循环
try:
# 1、接收命令 (命令:执行系统命令)
res = conn.recv(8096) # b'get a.txt
# 2、解析命令,提取相应的命令参数
cmds = res.decode("utf-8").split()
if cmds[0] == "get":
get(conn, cmds)
elif cmds[0] == "put":
put(conn, cmds)
except ConnectionRefusedError:
break
conn.close()
phone.close()
if __name__ == "__main__": #如果是执行当前文件的时候,这个条件成立,就执行。如果当前文件被其他文件当成模块导入的时候,这个条件是不成立的,里面的代码是不执行的
run()
客户端
import socket
import struct
import json
download_dir = r"F:\project\book\chapter6\文件传输\函数版本\client\download"
def get(phone, cmds):
# 2、以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户端的新文件中
# 第一步:先收报头的长度
header = phone.recv(4)
header_size = struct.unpack("i", header)[0]
# 第二步:再接收报头信息
header_bytes = phone.recv(header_size)
# 第三步:从报头中解析出对真实数据的描述信息
header_json = header_bytes.decode("utf-8")
header_dic = json.loads(header_json)
print(header_dic)
file_size = header_dic["file_size"]
filename = header_dic["filename"]
# 第四步:接受真实的数据
with open("%s/%s" % (download_dir, filename), "wb")as f:
recv_size = 0
while recv_size < file_size:
line = phone.recv(1024)
f.write(line)
recv_size += len(line)
print("总大小:%s 已下载大小:%s" % (file_size, recv_size))
def put(phone, cmds):
pass
def run():
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(("127.0.0.1", 9909)) # phone相当于服务端的conn
while True:
# 1、发命令
inp = input(">> ").strip() # get a.txt
if not inp:
continue
phone.send(inp.encode("utf-8"))
cmds = inp.split() # ["get","a.txt"]
if cmds[0] == "get":
get(phone, cmds)
elif cmds[0] == "put":
put(phone, cmds)
phone.close()
if __name__ == "__main__": # 如果是执行当前文件的时候,这个条件成立,就执行。如果当前文件被其他文件当成模块导入的时候,这个条件是不成立的,里面的代码是不执行的
run()
类版本
服务端
import socket
import subprocess
import struct
import json
import os
# 面相对象的好处可以把数据和操作数据的方法整合到一起
class MYServer:
address_family = socket.AF_INET
socket_type = socket.SOCK_STREAM
max_packet_size = 8192
coding = "utf-8"
request_queue_size = 5
allow_reuse_address = False # 允许地址再用
server_dir = r"F:\project\book\chapter6\文件传输\函数版本\server\share"
def __init__(self, server_address, bind_and_activate=True):
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 EOFError:
self.server_close()
raise
def server_bind(self):
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() # 本机的IP和端口号
def server_activate(self):
self.socket.listen(self.request_queue_size)
def server_close(self):
self.socket.close()
def get_request(self):
return self.socket.accept()
def close_request(self, request):
request.close()
def run(self):
while True: # 循环链接
self.conn, self.client_addr = self.get_request() # conn套接字对象
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) # path
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 ConnectionRefusedError:
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))
def get(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)
server = MYServer(('127.0.0.1', 8080))
server.run()
客户端
import socket
import struct
import json
import os
class MYClient:
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 EOFError:
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')
def get(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))
else:
print('download successful')
client = MYClient(('127.0.0.1', 8080))
client.run()

浙公网安备 33010602011771号