文件传输
简单的文件传输功能
目录结构:
server.py
import socket
import os
import json
import struct
IP = "127.0.0.1"
PORT = 9090
SHAR_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输\server\share"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((IP, PORT))
server.listen(5)
while True:
print("等待连接...")
conn, client_addr = server.accept()
print("客户端已建立连接,客户端地址为:", client_addr)
while True:
try:
# 1. 收命令
res = conn.recv(1024)
if not res: break # 适用于Linux系统
# 2. 解析命令,提取相应命令的参数
cmds = res.decode("utf-8").split()
filename = cmds[1]
# 3. 已读的方式打开文件,读取文件内容发送给客户端
# 第一步:制作固定长度的报头
head_dict = {
"filename": filename,
"md5": "xxxx",
"filesize": os.path.getsize("%s/%s" % (SHAR_DIR, filename))
}
head_json = json.dumps(head_dict)
head_bytes = head_json.encode("utf-8")
# 第二步:先发送报头的长度
conn.send(struct.pack('i', len(head_bytes)))
# 第三步:再发报头
conn.send(head_bytes)
# 第四步:再发送真实的数据
with open("%s/%s" % (SHAR_DIR, filename), "rb") as f:
for line in f:
conn.send(line)
except ConnectionResetError: # 适用于Windows系统
break
conn.close()
server.close()
client.py
import socket
import struct
import json
IP = "127.0.0.1"
PORT = 9090
DOWNLOAD_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输\client\download"
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((IP, PORT))
while True:
# 1. 发命令
cmds = input(">>: ").strip()
if not cmds: continue
client.send(cmds.encode("utf-8"))
# 2. 以写的方式打开一个新文件,接收服务端发来的文件的内容写入到客户端的新文件
# 第一步:先接收报头的长度
obj = client.recv(4)
head_size = struct.unpack("i", obj)[0]
# 第二步:再收报头
head_bytes = client.recv(head_size)
# 第三步:从报头中解析出对真实数据的描述信息
head_json = head_bytes.decode("utf-8")
head_dict = json.loads(head_json)
print(head_dict)
total_size = head_dict["filesize"]
filename = head_dict["filename"]
# 第四步:接收真实数据
with open("%s/%s" % (DOWNLOAD_DIR, filename), "wb") as f:
recv_size = 0
while recv_size < total_size:
line = client.recv(1024)
f.write(line)
recv_size += len(line)
print("文件总大小:%s ,已接收:%s" % (total_size, recv_size))
client.close()
运行结果:
文件传输-函数版
改造为函数版,可实现 get, put 功能。
目录结构:
server.py
import socket
import os
import json
import struct
IP = "127.0.0.1"
PORT = 9090
SHARE_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输-01函数版\server\share"
def get(conn, cmds):
filename = cmds[1]
# 3. 已读的方式打开文件,读取文件内容发送给客户端
# 第一步:制作固定长度的报头
head_dict = {
"filename": filename,
"md5": "xxxx",
"filesize": os.path.getsize("%s/%s" % (SHARE_DIR, filename))
}
head_json = json.dumps(head_dict)
head_bytes = head_json.encode("utf-8")
# 第二步:先发送报头的长度
conn.send(struct.pack('i', len(head_bytes)))
# 第三步:再发报头
conn.send(head_bytes)
# 第四步:再发送真实的数据
with open("%s/%s" % (SHARE_DIR, filename), "rb") as f:
for line in f:
conn.send(line)
def put(conn, cmds):
print(cmds)
conn.send("ok".encode("utf-8"))
obj = conn.recv(4)
head_size = struct.unpack("i", obj)[0]
head_bytes = conn.recv(head_size)
head_json = head_bytes.decode("utf-8")
head_dict = json.loads(head_json)
print(head_dict)
total_size = head_dict["filesize"]
filename = head_dict["filename"]
# 第四步:接收真实数据
with open("%s/%s" % (SHARE_DIR, filename), "wb") as f:
recv_size = 0
while recv_size < total_size:
line = conn.recv(1024)
f.write(line)
recv_size += len(line)
print("文件总大小:%s ,已接收:%s" % (total_size, recv_size))
def run():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((IP, PORT))
server.listen(5)
while True:
print("等待连接...")
conn, client_addr = server.accept()
print("客户端已建立连接,客户端地址为:", client_addr)
while True:
try:
# 1. 收命令
res = conn.recv(1024)
if not res: break # 适用于Linux系统
# 2. 解析命令,提取相应命令的参数
cmds = res.decode("utf-8").split()
if cmds[0] == "get":
get(conn, cmds)
if cmds[0] == "put":
put(conn, cmds)
except ConnectionResetError: # 适用于Windows系统
break
conn.close()
server.close()
if __name__ == '__main__':
run()
client.py
import socket
import struct
import json
import os
IP = "127.0.0.1"
PORT = 9090
DOWNLOAD_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输-01函数版\client\download"
def get(client):
# 2. 以写的方式打开一个新文件,接收服务端发来的文件的内容写入到客户端的新文件
# 第一步:先接收报头的长度
obj = client.recv(4)
head_size = struct.unpack("i", obj)[0]
# 第二步:再收报头
head_bytes = client.recv(head_size)
# 第三步:从报头中解析出对真实数据的描述信息
head_json = head_bytes.decode("utf-8")
head_dict = json.loads(head_json)
print(head_dict)
total_size = head_dict["filesize"]
filename = head_dict["filename"]
# 第四步:接收真实数据
with open("%s/%s" % (DOWNLOAD_DIR, filename), "wb") as f:
recv_size = 0
while recv_size < total_size:
line = client.recv(1024)
f.write(line)
recv_size += len(line)
print("文件总大小:%s ,已接收:%s" % (total_size, recv_size))
def put(client, cmds):
res=client.recv(1024)
if res.decode("utf-8") == "ok":
filename = cmds[1]
head_dict = {
"filename": filename,
"md5": "xxxx",
"filesize": os.path.getsize("%s/%s" % (DOWNLOAD_DIR, filename))
}
head_json = json.dumps(head_dict)
head_bytes = head_json.encode("utf-8")
# 第二步:先发送报头的长度
client.send(struct.pack('i', len(head_bytes)))
client.send(head_bytes)
# 第四步:再发送真实的数据
with open("%s/%s" % (DOWNLOAD_DIR, filename), "rb") as f:
for line in f:
client.send(line)
def run():
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((IP, PORT))
while True:
# 1. 发命令
inp = input(">>: ").strip()
if not inp: continue
client.send(inp.encode("utf-8"))
cmds = inp.split()
if cmds[0] == "get":
get(client)
if cmds[0] == "put":
put(client, cmds)
client.close()
if __name__ == '__main__':
run()
文件传输-面向对象版
仅有put功能。
目录结构:
server.py (进行了一些改变,原版在Windows上不能成功运行)
import socket
import struct
import json
import os
class FTPServer:
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
AA = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输-02面向对象版"
server_dir = "file_upload"
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:
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() # ???
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()
print("from client: ", self.client_addr)
while True:
try:
head_struct = self.conn.recv(4)
print(head_struct)
if not head_struct: break
head_len = struct.unpack("i", head_struct)
print(head_len)
head_json = self.conn.recv(head_len[0]).decode(self.coding)
head_dic = json.loads(head_json)
print(head_dic)
cmd = head_dic["cmd"]
if hasattr(self, cmd):
getattr(self, cmd)(head_dic)
except Exception:
break
def put(self, args):
print("come in..")
file_path = os.path.normpath(os.path.join(self.AA, self.server_dir, args["filename"])) # ??
filesize = args["filesize"]
recv_size = 0
print("--->", file_path)
dirname = os.path.dirname(file_path)
if not os.path.exists(dirname):
os.mkdir(dirname)
with open(file_path, "wb") as f:
print("11111")
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 = FTPServer(("127.0.0.1", 8080))
tcpserver1.run()
client.py
import socket
import json
import os
import struct
class FTPClient:
address_family = socket.AF_INET
socket_type = socket.SOCK_STREAM
allow_reuse_address = False
max_packet_size = 8192
coding = "utf-8"
requset_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]
print(filename)
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("sendsize:%s " % send_size)
else:
print("upload successful")
client = FTPClient(('127.0.0.1', 8080))
client.run()
运行后在客户端输入: put test.mp4
共有 0 条评论