【问题标题】:Files not being received correctly when sent through sockets over LAN通过 LAN 上的套接字发送文件时未正确接收文件
【发布时间】:2016-12-28 07:07:27
【问题描述】:

我正在尝试构建一个应用程序,该应用程序将通过 Python 3.4 套接字模块通过无线 LAN 发送文件。它似乎能够在一个工作站内发送文件,但是当尝试在同一网络上的两台计算机之间发送文件时,计算机似乎只接收前几千字节,数量取决于发送时文件的总大小.

例如,发送了一个 127 字节的文件没有问题,但在一个 34,846 字节的文件中,只收到了 1,431 或 4,327 个字节(似乎只收到了这两个字节数,似乎在两者之间随机切换)和在一个 65,182 字节的文件中,只收到了 5,772 或 4,324 个字节(同样的情况)。从接收文件的内容来看,似乎是接收到的前几个字节。

两个系统都具有超过 2GB 的免费、可访问 RAM 和足够的存储空间。服务器运行在 Windows 8.1,Python 3.4.2,客户端是 Ubuntu 14.04 Linux,Python 3.4.0。

我的代码可能是零碎的,而且通常写得不好,因为我是一个没有受过正规计算机科学教育或任何显着经验的初学者,尤其是在网络编程方面。但是,我已经通过代码扎根并绞尽脑汁,没有给出明确的解决方案。

服务器(主机):

import os
import socket
import struct
import time
import hashlib

def md5(fname):
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as readFile:
        for chunk in iter(lambda: readFile.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

try:
    s = socket.socket()
    host = socket.gethostname()
    port = 26
    s.bind(("0.0.0.0", port))

    filename = input("File to send? ")

    fileLength = os.stat(filename).st_size
    print("Length:", fileLength, "bytes")
    fileLengthBytes = struct.pack(">L", fileLength)

    filenameBytes = bytes(filename, "ascii")
    filenameLength = struct.pack(">L", len(filenameBytes))

    checksum = md5(filename)
    checksumBytes = bytes(bytearray.fromhex(checksum))

    s.listen(5)
    while True:
        c, addr = s.accept()
        print("Connection from", addr)
        c.send(checksumBytes)
        time.sleep(0.1)
        c.send(filenameLength + fileLengthBytes)
        time.sleep(0.1)
        with open(filename, "rb") as f:
            c.send(filenameBytes + f.read())
        c.close()
finally:
    try:
        c.close()
    except NameError:
        pass
    except Exception as e:
        print(type(e), e.args, e)
    try:
        f.close()
    except NameError:
        pass
    except Exception as e:
        print(type(e), e.args, e)

客户(收件人):

import socket
import struct
import hashlib

def md5(fname):
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as readFile:
        for chunk in iter(lambda: readFile.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()


CHECKSUM_LENGTH = 16

try:
    s = socket.socket()
    host = socket.gethostname()
    port = 26

    ip = input("Connect to IP: ")

    s.connect((ip, port))

    initialChecksum = s.recv(CHECKSUM_LENGTH)

    received = s.recv(8)
    # 1st 4 bytes: filename length
    # 2nd 4 bytes: file contents length

    filenameLength = struct.unpack(">L", received[0:4])[0]
    fileLength = struct.unpack(">L", received[4:])[0]
    print("Length:", fileLength)

    bytesToReceive = filenameLength + fileLength
    receivedBytes = s.recv(bytesToReceive)

    filename = str(receivedBytes[0:filenameLength], "ascii")
    f = open(filename, "wb")
    f.write(receivedBytes[filenameLength:]) # Write file contents
    actualChecksum = bytes(bytearray.fromhex(md5(filename)))

    if initialChecksum == actualChecksum:
        print("Fully received", filename)
    else:
        print(filename, "not received correctly")
finally:
    try:
        f.close()
    except NameError:
        pass
    except Exception as e:
        print(type(e), e.args, e)
    try:
        s.close()
    except NameError:
        pass
    except Exception as e:
        print(type(e), e.args, e)

我知道我使用的 md5 函数似乎不适用于以下小文件,我假设为 4 KB。

问题出在哪里?如何解决?我错过了什么重要的事情吗?

【问题讨论】:

    标签: python sockets lan


    【解决方案1】:

    您只收到传输的前几个包。这是因为s.recv() 将接收已经到达客户端的字节,但最多是作为参数给出的数字。在本地机器上传输速度很快,你会收到更多。

    要获得传输的所有部分,您应该收集所有字节,直到达到预期长度。

    一个非常简单的方法是这样的:

    buffer = ''
    while len(buffer) < bytes_to_receive:
        buffer += s.recv(1500)
    

    1500 是典型的 LAN MTU,对于至少获得一个完整的软件包来说是一个很好的价值。给出的代码只是 Python 2 解释概念的一个简单示例。它需要改进和优化,如果您使用的是 Python 3,则需要适应字节。

    【讨论】:

    • 那么,我可以将buffer = '' 替换为buffer = b'' 就可以了吗?这种方法会引发什么问题?
    • 应该可以,试一试!还有像 io.BytesIO 这样的东西,用于在 Python 3 中进行缓冲。
    猜你喜欢
    • 2016-12-08
    • 2019-12-28
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2021-09-15
    相关资源
    最近更新 更多