Python网络编程--实践心得

 1. 基于TCP协议的文件上传和下载

 通过输入get/put file_path来实现对于文件的上传到服务端和从服务端下载文件,也可以对传输的文件进行MD5 check.

但是缺点很多,输入指令麻烦,只是在本地测试,只是单行,没有实现并发效果.现在这只是针对TCP粘包问题的小测试

# _*_ coding utf-8 _*_
# george
# time: 2024/1/30上午9:26
# name: cmd_file_server.py
# comment: 文件传输服务端
import socket
import json
import hashlib
from pathlib import Path


# 获取传递文件的md5值
def get_md5(cmd_path: str) -> str:
    file_path = Path(cmd_path)
    with open(file_path, "rb") as f:
        m1 = hashlib.md5(f.read())
    return m1.hexdigest()


# 传输文件给客户端:
def transfer_to_client(request_file, conn):
    f = Path(request_file)
    header = {
        "file_name": f.name,
        "file_size": f.stat().st_size,
        "md5": get_md5(request_file)
    }
    header_json = json.dumps(header)
    header_bytes = header_json.encode("utf-8")
    header_h = bytes(str(len(header_bytes)), "utf-8").zfill(4)
    conn.send(header_h)
    conn.send(header_bytes)
    with open(request_file, "rb") as f:
        while True:
            res = f.read(1024)
            if not res:
                break
            conn.send(res)
    print("文件传输完毕")


def receive_from_client(conn):
    # 先拿头部长度
    header_size = int(conn.recv(4).decode("utf-8"))
    print("hear_size",header_size)
    # 拿头部信息
    header_json = conn.recv(header_size).decode("utf-8")
    header = json.loads(header_json)
    print(f"客户端传递文件的头部:{header}")
    data_size = header["file_size"]
    recv_size = 0
    # data = b'' # 如果是大文件,就开一个文件,边收便往文件里面写
    save_file_path = Path.home() / "Desktop" / "server" / header["file_name"]
    # 文件接收
    with open(save_file_path, "wb") as f:
        while recv_size < data_size:
            res = conn.recv(1024)
            recv_size += len(res)
            f.write(res)
    print("数据接收成功")
    # MD5 check
    save_file_md5 = get_md5(save_file_path)
    if save_file_md5 == header["md5"]:
        print("MD5 check pass 数据完整性校验成功")
    else:
        print("MD5 check fail 数据完整性校验失败")


def main():
    sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.bind(("0.0.0.0", 5002))
    sk.listen(5)
    print("服务端启动成功,在5000端口等待连接")
    while True:  # 服务端 --> 连接循环
        conn, addr = sk.accept()  # windows客户端异常断开连接
        print(f"连接对象是:{conn}")
        print(f"ip和端口为:{addr}")
        # 5. 数据传输
        while True:
            try:
                cmd = conn.recv(1200)
            except:
                break
            if not cmd:  # mac客户端异常断开连接
                break
            data = cmd.decode("utf-8")
            print(f"客户端发送过来的数据为:{data}")
            if data == "q":
                break
            op, client_file_path = data.split()
            if op == "get":
                transfer_to_client(client_file_path, conn)
            if op == "put":
                receive_from_client(conn)

        # 6. 结束服务
        conn.close()

    # 7. 关闭server(可选)
    # sk.close()


if __name__ == "__main__":
    main()
# _*_ coding utf-8 _*_
# george
# time: 2024/1/30上午9:26
# name: cmd_file_client.py
# comment: 文件传输客户端
import socket
import json
import hashlib
from pathlib import Path


# 获取传递文件的md5值
def get_md5(cmd_path: str) -> str:
    file_path = Path(cmd_path)
    with open(file_path, "rb") as f:
        m1 = hashlib.md5(f.read())
    return m1.hexdigest()


# 下载文件
def download_file(cmd):
    while True:
        if not cmd:  # 避免发空问题
            continue
        if cmd == "q":
            break
        sk.send(cmd.encode("utf-8"))
        # 先拿头部长度
        header_size = int(sk.recv(4).decode("utf-8"))
        # 拿头部信息
        header_json = sk.recv(header_size).decode("utf-8")
        header = json.loads(header_json)
        print(header)
        data_size = header["file_size"]
        recv_size = 0
        # data = b'' # 如果是大文件,就开一个文件,边收便往文件里面写
        save_file_path = Path.home() / "Desktop" / "tt" / header["file_name"]
        # 文件接收
        with open(save_file_path, "wb") as f:
            while recv_size < data_size:
                res = sk.recv(1024)
                recv_size += len(res)
                f.write(res)
        print("数据接收成功")
        # MD5 check
        save_file_md5 = get_md5(save_file_path)
        if save_file_md5 == header["md5"]:
            print("MD5 check pass 数据完整性校验成功")
            break
        else:
            print("MD5 check fail 数据完整性校验失败")
            break
    # 4.关闭连接
    sk.close()


# 上传文件
def upload_file(cmd):
    while True:
        if not cmd:  # 避免发空问题
            continue
        if cmd == "q":
            break
        sk.send(cmd.encode("utf-8"))
        op, request_file = cmd.split()
        f = Path(request_file)
        header = {
            "file_name": f.name,
            "file_size": f.stat().st_size,
            "md5": get_md5(request_file)
        }
        header_json = json.dumps(header)
        header_bytes = header_json.encode("utf-8")
        header_h = bytes(str(len(header_bytes)), "utf-8").zfill(4)
        sk.send(header_h)
        sk.send(header_bytes)
        with open(request_file, "rb") as f:
            while True:
                res = f.read(1024)
                if not res:
                    break
                sk.send(res)
        print("文件传输完毕")
        break
    # 4.关闭连接
    sk.close()


if __name__ == "__main__":
    sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.connect(("0.0.0.0", 5002))
    cmd = input("请输入文件传入路径>>>").strip()
    op = cmd.split()[0]
    if op == "get":
        download_file(cmd)
    if op == "put":
        upload_file(cmd)
    else:
        exit(0)

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值