Python socket实现ftp文件下载服务

简要

使用Python socket和多线程实现一个FTP服务下载。下面的示例是固定下载某一个任意格式文件。

仅仅为了展示如果使用socket和多线程进行文件下载

服务端代码


import socket
import threading
import os
# file = r"D:\var\log\abc.log"
file = r"D:\var\log\rabbitmq-server-3.7.2.exe"

def one_socket_thread(conn:socket.socket, addr):
"""
每次有一个连接,就启动一个线程进行处理
:param conn:
:return:
"""
byte_size_per_time = 1024*1024
index = 0

# 首先要告诉客户端,文件的大小
conn.recv(byte_size_per_time)
conn.send(str(os.path.getsize(file)).encode("utf-8"))

with open(file, "rb") as fh:
while True: # 一直在一个socket连接以内
socket_raw_receive = conn.recv(byte_size_per_time) # 从socket客户端接收数据
if not socket_raw_receive: # 如果从socket连接的客户端接收不到数据的话,就结束
break
fh.seek(index) # 跳到指定索引位置
content = fh.read(byte_size_per_time)
conn.send(content) # 往socket客户端发送数据
index += byte_size_per_time
print("[{}] has completed and close socket".format(addr))
conn.close()

def main():
ip_port = ("127.0.0.1", 9000)
sk_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk_server.bind(ip_port)
sk_server.listen(5) # 最多有5个连接
print("Waiting for connection ...")
while True:
conn, addr = sk_server.accept()
threading.Thread(target=one_socket_thread, args=(conn, addr)).start()


if __name__ == '__main__':
main()
 

 客户端代码

import socket

file = r"D:\var\log\rabbitmq-server-3.7.2.copy.exe"

def download():
    ip_port = ("127.0.0.1", 9000)
    byte_size_per_time = 102
    sk_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk_client.connect(ip_port)

    # 首先获取到文件的大小
    sk_client.send(b"OK")
    source_file_size = int(sk_client.recv(1024).decode("utf-8"))

    total_download_size = 0 # 记录总共下载了多少数据
    with open(file, "wb") as fh:
        while True:
            sk_client.send(b"OK") # 如果文件没有下载完的话,客户端给服务端发送这个消息,接着下载
            content = sk_client.recv(byte_size_per_time)
            fh.write(content)
            total_download_size += len(content)
            if total_download_size == source_file_size: # 说明此时已经是最后一笔数据了,马上就下载完
                sk_client.send(b"")
                break
    print("File [{}] has downloaded successfully".format(file))
    sk_client.close()

if __name__ == '__main__':
    download()

 

posted @ 2021-01-15 10:29  JCL_1023  阅读(155)  评论(0编辑  收藏  举报