将多个文件从一台主机传输到另一台主机
Transferring multiple files from one host to another
我是 python 套接字编程的新手。我想将 5 个文件(照片)从 mininet 中的一台主机传输到另一台主机。这些文件的名称分别编号(我的意思是 1.jpg、2.jpg 和 ...)。问题是当我 运行 这些代码时,第一张照片传输正确但其他照片损坏。有什么问题:
sender.py
import socket
import sys
buf = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.0.0.1',12345))
for i in range(1,6):
with open("%d.jpg" % (i),'rb') as f:
data = f.read(buf)
while 1:
if not data:
break
s.sendall(data)
data = f.read(buf)
s.close()
receiver.py:
import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('10.0.0.1', 12345))
buf = 1024
s.listen(1)
conn , addr = s.accept()
for i in range(6,11):
with open("%d.jpg" % (i),'wb') as f:
while 1:
data = conn.recv(buf)
#print(data[:10])
#print "PACKAGE RECEIVED..."
f.write(data)
if not data: break
#conn.close()
#s.close()
你应该像这样使用它:
with open("%d.jpg" % (i),'wb') as f:
while 1:
data = conn.recv(buf)
#print(data[:10])
#print "PACKAGE RECEIVED..."
f.write(data)
if not data: break
这样,当您离开 with 块时,当您退出 while.
时,f 会自动关闭
我想您需要扩展协议,以便接收方知道它得到了什么,并且您可以让它据此采取行动。类似于 'begin-of-transfer' ... 发送文件名,发送数据,发送 'end-of-transfer' 使接收方关闭文件
解决您问题的简单方法是为每个文件创建一个新连接。下面的代码就是这样做的。
发件人
from __future__ import print_function
import socket
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def send_file(fname):
with open(fname, 'rb') as f:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except socket.error as err:
print(err, HOST, PORT)
sock.close()
return
while True:
data = f.read(BUFSIZE)
if not data:
break
while data:
sent = sock.send(data)
data = data[sent:]
sock.close()
fnames = [
'test0.jpg',
'test1.jpg',
'test2.jpg',
'test3.jpg',
]
def main():
for fname in fnames:
send_file(fname)
if __name__ == '__main__':
main()
接收者
from __future__ import print_function
import socket
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind((HOST, PORT))
except socket.error as err:
print('Bind failed', err)
return
sock.listen(1)
print('Socket now listening at', HOST, PORT)
file_number = 0
try:
while True:
conn, addr = sock.accept()
print('Connected with', *addr)
fname = 'image%d.jpg' % file_number
with open(fname, 'wb') as f:
while True:
data = conn.recv(BUFSIZE)
if not data:
break
f.write(data)
conn.close()
print(fname, 'saved\n')
file_number += 1
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
sock.close()
if __name__ == '__main__':
main()
您需要按 CtrlC 或 Break(取决于您的 OS) 退出接收器。
但是在接收方使用这些数字文件名并不是很令人满意,所以我决定让它更复杂一些。 :) 在以下版本中,我们在文件数据之前发送文件名。这有点棘手,因为接收方需要将文件名与实际文件数据分开。如果每个 socket.recv
调用对应一个 socket.send
调用,那将很容易,但不能保证会发生:接收到的字节可能与发送时的分割方式不同。接收方需要缓冲字节,以便正确分解它们。有关详细信息,请参阅 Socket Programming HOWTO。
为了让接收方知道文件名在哪里结束,我们首先发送一个编码文件名长度的字节。一个字节可以包含 0 到 255 之间的数字,因此这段代码不能处理比这更长的文件名。在长度字节之后,我们发送使用 UTF-8 编码的文件名本身。然后我们发送实际的文件内容。
接收器使用一个名为 class 的 Receiver 来处理缓冲。这个 class 有一个 .get
方法,我们可以用它来获取指定数量的字节。我们使用该方法来获取文件名长度和文件名。然后我们使用Receiver的.save
方法将接收到的文件内容保存到一个新文件中。
这段代码有点乱,因为它被设计为 运行 on Python 2 和 Python 3,任意组合。如果它仅用于 Python 3,它会更整洁一些。我硬编码 'localhost' 作为主机名,因为我只有一台计算机,所以我无法通过网络测试它,但我相信它会在网络上正常工作。
发件人:
from __future__ import print_function
import socket
from struct import pack
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def send(sock, data):
while data:
sent = sock.send(data)
data = data[sent:]
def send_file(fname):
with open(fname, 'rb') as f:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except socket.error as err:
print(err, HOST, PORT)
sock.close()
return
# Send the file name length & the filename itself in one packet
send(sock, pack('B', len(fname)) + fname.encode())
while True:
data = f.read(BUFSIZE)
if not data:
break
send(sock, data)
sock.close()
fnames = [
'test1.gif',
'test2.jpg',
'test3.png',
'test4.pdf',
]
def main():
for fname in fnames:
send_file(fname)
if __name__ == '__main__':
main()
这是接收者:
from __future__ import print_function
import socket
from struct import unpack
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind((HOST, PORT))
except socket.error as err:
print('Bind failed', err)
return
sock.listen(1)
print('Socket now listening at', HOST, PORT)
try:
while True:
conn, addr = sock.accept()
print('Connected with', *addr)
# Create a buffer for this connection
receiver = Receiver(conn)
# Get the length of the file name
name_size = unpack('B', receiver.get(1))[0]
# Get the file name itself
name = receiver.get(name_size).decode()
print('name', name)
# Save the file
receiver.save(name)
conn.close()
print('saved\n')
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
sock.close()
if __name__ == '__main__':
main()
我是 python 套接字编程的新手。我想将 5 个文件(照片)从 mininet 中的一台主机传输到另一台主机。这些文件的名称分别编号(我的意思是 1.jpg、2.jpg 和 ...)。问题是当我 运行 这些代码时,第一张照片传输正确但其他照片损坏。有什么问题:
sender.py
import socket
import sys
buf = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.0.0.1',12345))
for i in range(1,6):
with open("%d.jpg" % (i),'rb') as f:
data = f.read(buf)
while 1:
if not data:
break
s.sendall(data)
data = f.read(buf)
s.close()
receiver.py:
import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('10.0.0.1', 12345))
buf = 1024
s.listen(1)
conn , addr = s.accept()
for i in range(6,11):
with open("%d.jpg" % (i),'wb') as f:
while 1:
data = conn.recv(buf)
#print(data[:10])
#print "PACKAGE RECEIVED..."
f.write(data)
if not data: break
#conn.close()
#s.close()
你应该像这样使用它:
with open("%d.jpg" % (i),'wb') as f:
while 1:
data = conn.recv(buf)
#print(data[:10])
#print "PACKAGE RECEIVED..."
f.write(data)
if not data: break
这样,当您离开 with 块时,当您退出 while.
时,f 会自动关闭我想您需要扩展协议,以便接收方知道它得到了什么,并且您可以让它据此采取行动。类似于 'begin-of-transfer' ... 发送文件名,发送数据,发送 'end-of-transfer' 使接收方关闭文件
解决您问题的简单方法是为每个文件创建一个新连接。下面的代码就是这样做的。
发件人
from __future__ import print_function
import socket
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def send_file(fname):
with open(fname, 'rb') as f:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except socket.error as err:
print(err, HOST, PORT)
sock.close()
return
while True:
data = f.read(BUFSIZE)
if not data:
break
while data:
sent = sock.send(data)
data = data[sent:]
sock.close()
fnames = [
'test0.jpg',
'test1.jpg',
'test2.jpg',
'test3.jpg',
]
def main():
for fname in fnames:
send_file(fname)
if __name__ == '__main__':
main()
接收者
from __future__ import print_function
import socket
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind((HOST, PORT))
except socket.error as err:
print('Bind failed', err)
return
sock.listen(1)
print('Socket now listening at', HOST, PORT)
file_number = 0
try:
while True:
conn, addr = sock.accept()
print('Connected with', *addr)
fname = 'image%d.jpg' % file_number
with open(fname, 'wb') as f:
while True:
data = conn.recv(BUFSIZE)
if not data:
break
f.write(data)
conn.close()
print(fname, 'saved\n')
file_number += 1
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
sock.close()
if __name__ == '__main__':
main()
您需要按 CtrlC 或 Break(取决于您的 OS) 退出接收器。
但是在接收方使用这些数字文件名并不是很令人满意,所以我决定让它更复杂一些。 :) 在以下版本中,我们在文件数据之前发送文件名。这有点棘手,因为接收方需要将文件名与实际文件数据分开。如果每个 socket.recv
调用对应一个 socket.send
调用,那将很容易,但不能保证会发生:接收到的字节可能与发送时的分割方式不同。接收方需要缓冲字节,以便正确分解它们。有关详细信息,请参阅 Socket Programming HOWTO。
为了让接收方知道文件名在哪里结束,我们首先发送一个编码文件名长度的字节。一个字节可以包含 0 到 255 之间的数字,因此这段代码不能处理比这更长的文件名。在长度字节之后,我们发送使用 UTF-8 编码的文件名本身。然后我们发送实际的文件内容。
接收器使用一个名为 class 的 Receiver 来处理缓冲。这个 class 有一个 .get
方法,我们可以用它来获取指定数量的字节。我们使用该方法来获取文件名长度和文件名。然后我们使用Receiver的.save
方法将接收到的文件内容保存到一个新文件中。
这段代码有点乱,因为它被设计为 运行 on Python 2 和 Python 3,任意组合。如果它仅用于 Python 3,它会更整洁一些。我硬编码 'localhost' 作为主机名,因为我只有一台计算机,所以我无法通过网络测试它,但我相信它会在网络上正常工作。
发件人:
from __future__ import print_function
import socket
from struct import pack
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def send(sock, data):
while data:
sent = sock.send(data)
data = data[sent:]
def send_file(fname):
with open(fname, 'rb') as f:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except socket.error as err:
print(err, HOST, PORT)
sock.close()
return
# Send the file name length & the filename itself in one packet
send(sock, pack('B', len(fname)) + fname.encode())
while True:
data = f.read(BUFSIZE)
if not data:
break
send(sock, data)
sock.close()
fnames = [
'test1.gif',
'test2.jpg',
'test3.png',
'test4.pdf',
]
def main():
for fname in fnames:
send_file(fname)
if __name__ == '__main__':
main()
这是接收者:
from __future__ import print_function
import socket
from struct import unpack
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind((HOST, PORT))
except socket.error as err:
print('Bind failed', err)
return
sock.listen(1)
print('Socket now listening at', HOST, PORT)
try:
while True:
conn, addr = sock.accept()
print('Connected with', *addr)
# Create a buffer for this connection
receiver = Receiver(conn)
# Get the length of the file name
name_size = unpack('B', receiver.get(1))[0]
# Get the file name itself
name = receiver.get(name_size).decode()
print('name', name)
# Save the file
receiver.save(name)
conn.close()
print('saved\n')
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
sock.close()
if __name__ == '__main__':
main()