通过 LAN 上的套接字发送时未正确接收文件
Files not being received correctly when sent through sockets over LAN
我正在尝试构建一个应用程序,它将通过 Python 3.4 套接字模块通过无线 LAN 发送文件。它似乎能够在一个工作站内发送文件,但是当试图在同一网络上的两台计算机之间发送文件时,计算机似乎只接收到前几千字节,数量取决于发送时文件的总大小.
比如发送一个127字节的文件没有问题,但是一个34846字节的文件,只收到了1431或者4327字节(好像只收到了这两个字节,貌似是随机切换的) ) 而对于一个 65,182 字节的文件,只收到了 5,772 或 4,324 字节(同样的情况)。从接收到的文件内容来看,似乎是接收到的前几个字节。
两个系统都有超过 2GB 的可用可用 RAM 和足够的存储空间 space。服务器 运行 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。
问题出在哪里?如何解决?我错过了什么重要的东西吗?
您只收到传输的前几个包。这是因为 s.recv()
将接收已经到达客户端的字节,但最多是作为参数给出的数字。在本地机器上传输很快,你会收到更多。
要获得传输的所有部分,您应该收集所有字节,直到达到预期长度。
一个非常简单的方法是这样的:
buffer = ''
while len(buffer) < bytes_to_receive:
buffer += s.recv(1500)
1500 是典型的 LAN MTU,对于至少获得完整包来说是一个不错的价值。给出的代码只是一个简单的例子Python 2 来解释概念。它需要改进和优化,如果你使用 Python 3,适应字节。
我正在尝试构建一个应用程序,它将通过 Python 3.4 套接字模块通过无线 LAN 发送文件。它似乎能够在一个工作站内发送文件,但是当试图在同一网络上的两台计算机之间发送文件时,计算机似乎只接收到前几千字节,数量取决于发送时文件的总大小.
比如发送一个127字节的文件没有问题,但是一个34846字节的文件,只收到了1431或者4327字节(好像只收到了这两个字节,貌似是随机切换的) ) 而对于一个 65,182 字节的文件,只收到了 5,772 或 4,324 字节(同样的情况)。从接收到的文件内容来看,似乎是接收到的前几个字节。
两个系统都有超过 2GB 的可用可用 RAM 和足够的存储空间 space。服务器 运行 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。
问题出在哪里?如何解决?我错过了什么重要的东西吗?
您只收到传输的前几个包。这是因为 s.recv()
将接收已经到达客户端的字节,但最多是作为参数给出的数字。在本地机器上传输很快,你会收到更多。
要获得传输的所有部分,您应该收集所有字节,直到达到预期长度。
一个非常简单的方法是这样的:
buffer = ''
while len(buffer) < bytes_to_receive:
buffer += s.recv(1500)
1500 是典型的 LAN MTU,对于至少获得完整包来说是一个不错的价值。给出的代码只是一个简单的例子Python 2 来解释概念。它需要改进和优化,如果你使用 Python 3,适应字节。