082. 编写一个函数,实现简单的文件服务器功能

在 Python 中,可以使用 socket 模块来实现一个简单的文件服务器。这个服务器可以接收客户端的请求,发送文件内容给客户端,或者接收客户端上传的文件并保存到服务器上。

示例代码

以下代码实现了一个简单的文件服务器,支持文件上传和下载。

import socket
import threading
import os

def handle_client(client_socket, client_address, server_dir):
    """
    处理客户端请求的函数

    :param client_socket: 客户端套接字
    :param client_address: 客户端地址
    :param server_dir: 服务器文件目录
    """
    print(f"连接来自 {client_address}")
    try:
        while True:
            request = client_socket.recv(1024).decode('utf-8')
            if not request:
                break

            command, *args = request.split()
            if command == "UPLOAD":
                file_name = args[0]
                file_path = os.path.join(server_dir, file_name)
                with open(file_path, 'wb') as file:
                    while True:
                        data = client_socket.recv(1024)
                        if data.endswith(b"<EOF>"):
                            file.write(data[:-5])
                            break
                        file.write(data)
                print(f"文件 {file_name} 已上传")
            elif command == "DOWNLOAD":
                file_name = args[0]
                file_path = os.path.join(server_dir, file_name)
                if os.path.exists(file_path):
                    with open(file_path, 'rb') as file:
                        data = file.read()
                        client_socket.sendall(data + b"<EOF>")
                else:
                    client_socket.sendall(b"File not found<EOF>")
            elif command == "LIST":
                files = os.listdir(server_dir)
                file_list = "\n".join(files)
                client_socket.sendall(file_list.encode('utf-8') + b"<EOF>")
            else:
                client_socket.sendall(b"Unknown command<EOF>")
    finally:
        client_socket.close()
        print(f"连接 {client_address} 已关闭")

def start_file_server(host='127.0.0.1', port=65432, server_dir='server_files'):
    """
    启动文件服务器

    :param host: 服务器地址,默认为 localhost
    :param port: 服务器端口,默认为 65432
    :param server_dir: 服务器文件目录,默认为 'server_files'
    """
    if not os.path.exists(server_dir):
        os.makedirs(server_dir)

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((host, port))
    server_socket.listen()
    print(f"文件服务器启动,监听地址 {host}:{port}")

    try:
        while True:
            client_socket, client_address = server_socket.accept()
            client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address, server_dir))
            client_thread.start()
    except KeyboardInterrupt:
        print("服务器关闭")
    finally:
        server_socket.close()

# 主函数
if __name__ == "__main__":
    start_file_server()

代码说明

服务器初始化

  • 使用 socket.socket 创建一个 TCP 套接字。

  • 使用 bind 方法绑定到指定的地址和端口。

  • 使用 listen 方法开始监听连接请求。

处理客户端请求

  • 使用 accept 方法接受客户端的连接。

  • 为每个客户端创建一个线程来处理请求。

支持以下命令:

  • UPLOAD <file_name>:上传文件。

  • DOWNLOAD <file_name>:下载文件。

  • LIST:列出服务器上的文件。

文件上传

  • 接收文件内容并保存到指定目录。

  • 使用 <EOF> 标记文件传输结束。

文件下载

  • 读取文件内容并发送给客户端。

  • 使用 <EOF> 标记文件传输结束。

文件列表:列出服务器目录中的所有文件并发送给客户端。

异常处理:捕获异常并确保客户端连接在结束时正确关闭。

示例输出

假设运行上述代码,服务器将启动并监听指定的地址和端口。当客户端连接并发送请求时,服务器将处理请求并返回结果。

注意事项

安全性

  • 在实际应用中,需要对客户端的请求进行验证,避免路径遍历攻击。

  • 可以添加身份验证机制,确保只有授权用户可以访问文件。

错误处理:在实际应用中,建议添加更详细的异常处理机制,以处理网络错误、文件读写错误等情况。

停止服务器:在实际应用中,可以设置一个条件变量或信号处理机制,以便在需要时停止服务器。

扩展功能

  1. 支持更多文件操作:添加文件删除、重命名等功能。
  2. 支持大文件传输:使用更高效的方式处理大文件传输,例如分块传输。
  3. 支持多用户:添加用户管理功能,支持多用户同时连接。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)