#服务器端
#==========================================================================
import socket
import os
# 创建传输任务
def read_send_task(file_path, service_client_scoket):
# 二进制方式打开源文件
with open(file_path, 'rb') as file:
while True:
file_data = file.read(1024)
print("正在读取文件...")
if file_data:
print("正在发送数据...")
service_client_scoket.send(file_data)
else:
service_client_socket.send(b"trans_end")
print("读取文件并发送数据完成!")
break
def send_task(service_client_socket, share_dir):
# 接收客户端请求的文件名列表
file_name_list = service_client_socket.recv(1024).decode('gbk').split(",")
print("客户端请求的文件列表", file_name_list)
for file_name in file_name_list:
print("准备发送文件", file_name)
service_client_socket.send(file_name.encode('gbk'))
# 等待客户端确认,并准备发送文件内容
ack = service_client_socket.recv(1024)
if ack == b'ok':
file_path = share_dir + "/" + file_name
# 调用传输任务,向客户端发送文件
read_send_task(file_path, service_client_socket)
flag = service_client_socket.recv(1024).decode('gbk')
if flag == "1":
print("开始发送下一个文件")
continue
# 主函数入口
if __name__ == '__main__':
# 设置文件共享目录
share_dir = "/home/test"
# 创建tcp套接字
file_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用
file_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定ip和端口
file_server_socket.bind(("", 5858))
# 设置监听
file_server_socket.listen(128)
# 接收客户端连接请求,返回新的套接字服务于客户端
service_client_socket, ip_port = file_server_socket.accept()
# 获取共享目录的文件列表,转换为str类型,发送给客户端
file_list = os.listdir(share_dir)
file_str = ",".join(file_list)
service_client_socket.send(file_str.encode('gbk'))
# 接收客户端请求列表,并向客户端发送相应文件
send_task(service_client_socket, share_dir)
# 关闭新的套接字
service_client_socket.close()
# 关闭服务端套接字
file_server_socket.close()
#==========================================================================
#客户端
import socket
import os
# 下载模式
def mode_opt(require_list, recv_file_list):
# 选择要下载的模式
print("=" * 30)
print("1(下载单个或者多个文件)")
print("2(下载文件夹的所有文件)")
print("=" * 30)
opt_num = input("请选择:")
# 单或多文件下载,对文件名判断是否存在,存在则加入请求列表
if opt_num == "1":
while True:
file_name = input("输入要下载的文件名:")
if file_name in recv_file_list:
require_list.append(file_name)
else:
print("请求的文件不存在!")
continue
opt_num1 = input("1 继续添加,2 不添加了")
if opt_num1 == "1":
continue
elif opt_num1 == "2":
break
else:
print("输入错误!")
break
# 所有文件下载,将目录列表直接复制给请求列表
if opt_num == "2":
for file_name in recv_file_list:
require_list.append(file_name)
# 循环接收服务端的发来的文件
def recv_from_filesvr(client_socket, file_dir):
# 设置循环
while True:
# 等待接收服务器发送的文件名
file_name = client_socket.recv(1024).decode('gbk')
# 如果文件名不为空,拼接新的文件名
if file_name:
print("即将下载文件", file_name)
# 向服务端发送收到文件名的确认消息,等待接收文件内容
client_socket.send(b"ok")
# 拼接文件名
file_path = file_dir + '/' + file_name
# 打开文件并将接收的二进制数据写入文件
with open(file_path, 'wb') as file:
while True:
recv_data = client_socket.recv(1024)
# 如果读取内容不为空,且没有出现trans_end标记,则持续向文件写入接收的内容,如果为空,退出循环
if recv_data:
# 如果读取的内容出现标记,则剔除标记,将剩余内容写入文件,并退出写文件循环
if recv_data.endswith(b'trans_end'):
recv_data = recv_data.replace(b'trans_end', b'')
file.write(recv_data)
print("%s下载完成!" % file_name)
# 向服务端发送文件写入完成,等待发送下个文件
client_socket.send("1".encode('gbk'))
print("准备下载下一个文件")
break
else:
file.write(recv_data)
print("正在下载...")
else:
print("收到的文件名为空!程序结束")
break
# 创建tcp套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接
client_socket.connect(("127.0.0.1", 5858))
# 接收服务端的文件列表
recv_file_list_data = client_socket.recv(1024)
recv_file_list = recv_file_list_data.decode('gbk').split(",")
print(recv_file_list)
# 指定目录,接收服务端的文件
file_dir = input("设置下载路径:")
# 如果目录存在直接下载,不存在则创建目录
if not os.path.exists(file_dir):
print("目录不存在,系统自动创建目录")
os.mkdir(file_dir)
# 创建客户端请求列表
require_list = []
# 调用下载模式
mode_opt(require_list, recv_file_list)
print(require_list)
print("hello")
# 向服务器发送要下载的文件列表,将列表转换为str发送
require_str = ",".join(require_list)
client_socket.send(require_str.encode('gbk'))
# 调用接收函数,接收服务器发送的文件名和文件内容
recv_from_filesvr(client_socket, file_dir)
# 关闭套接字
client_socket.close()