Python 将多个文件从一台主机传输到另一台主机

Python 将多个文件从一台主机传输到另一台主机,python,sockets,mininet,Python,Sockets,Mininet,我是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)

我是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
这样,当您退出while时,当您离开with块时,f将自动关闭


我想你需要扩展协议,这样接收者就知道它得到了什么,你就可以让它去做。像“开始转移”之类的东西。。。发送文件名、发送数据、发送“传输结束”以使接收者关闭文件

解决问题的简单方法是为每个文件创建一个新连接。下面的代码就是这样做的

发件人 接受者 这是接收器:

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()
from\uuuuu future\uuuuu导入打印功能
导入套接字
从结构导入解包
主机='localhost'
端口=12345
BUFSIZE=4096
类别接收人:
''来自套接字连接''的缓冲区二进制数据'
定义初始化(自身,连接):
self.conn=conn
self.buff=bytearray()
def get(自身,大小):
''从缓冲区获取大小字节,正在读取
必要时从康涅狄格州
'''
而len(self.buff)<大小:
数据=self.conn.recv(BUFSIZE)
如果没有数据:
打破
self.buff.extend(数据)
#提取所需的字节
结果=self.buff[:大小]
#并将其从缓冲区中移除
del self.buff[:大小]
返回字节(结果)
def保存(自我,fname):
''将剩余字节保存到文件fname''
将open(fname,'wb')作为f:
如果self.buff:
f、 写入(字节(self.buff))
尽管如此:
数据=self.conn.recv(BUFSIZE)
如果没有数据:
打破
f、 写入(数据)
def main():
sock=socket.socket(socket.AF\u INET,socket.sock\u流)
sock.setsockopt(socket.SOL_socket,socket.SO_REUSEADDR,1)
尝试:
sock.bind((主机、端口))
除了socket.error作为错误:
打印('绑定失败',错误)
返回
短袜,听(1)
打印('正在侦听的套接字'、主机、端口)
尝试:
尽管如此:
conn,addr=sock.accept()
打印('Connected with',*addr)
#为此连接创建缓冲区
接收器=接收器(连接)
#获取文件名的长度
name_size=unpack('B',receiver.get(1))[0]
#获取文件名本身
name=receiver.get(name\u size).decode()
打印('名称',名称)
#保存文件
receiver.save(名称)
康涅狄格州关闭
打印('已保存\n')
#点击Break/Ctrl-C退出
除键盘中断外:
打印(“\nClosing”)
sock.close()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()

循环不会关闭打开的文件。因此,请在退出while后将其关闭,或者使用带有open(…)的
作为f:
将自动关闭打开的文件。I asume缓冲区中没有刷新数据case@hootnot退出while时是否应使用
f.flush()
?如果是这样,我在退出while时添加了
f.flush()
,但仍然不起作用。我也尝试了f.close(),但也没有解决问题。谢谢。我根据这个编辑了我的代码并更新了我的帖子。但它仍然不适用于多张照片。不,这是正确的。接收方需要准确地知道一个文件的数据结束位置和另一个文件的数据开始位置。因此,您需要有一个协议,以便他们能够相互理解。设置的方式并非如此。使用简单的文本标记,如“传输开始”和“传输结束”,是不安全的,因为数据可能包含“传输结束”标记,尽管这在JPEG数据中极不可能。但是获取文件大小很容易…是的,我明白你的意思,现在我想知道如何才能做到这一点。例如,我可以在每次传输结束时发送1或0位。1表示有另一个文件即将到来,在接收到该文件后,接收方将创建一个新文件,并写入从发送方发送的新数据。和0表示发件人已完成其所有文件。是否有可能或有更好的方法来执行此操作?检查现有协议(如SMTP),您可以在smtplib.py文件中找到详细信息。您的代码运行良好,说明完整且非常有用+对这个答案有100个答案。非常感谢。我的荣幸,海伦!复习我生锈的socket编程技能很有趣。亲爱的PM 2Ring,发送所有这些文件后,发送方是否可以发送一个简单的字符串,如“completed”,接收方是否可以在收到所有4个文件后收到此消息并打印出来?虽然这似乎不是一项艰巨的任务,但我没能成功地完成。
from __future__ import print_function
import socket

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)
    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()
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()