【问题标题】:How to send end of file without closing tcp socket如何在不关闭 tcp 套接字的情况下发送文件结尾
【发布时间】:2015-07-19 14:53:31
【问题描述】:

我正在尝试通过 Python 编码的对等聊天系统中的 tcp 套接字发送文件。接收套接字似乎不知道没有更多文件要接收。我可以让接收套接字不预测未到来的数据的唯一方法是关闭发送套接字(使用 socket.shutdown(socket.SHUT_WR))。但是,关闭发送套接字不是一种选择,因为我需要该套接字来发送其他消息。我首先尝试为文件发送/接收分配一个新端口,但失败了。现在,我尝试创建一个文件结尾“信号”,但它在接收端没有被识别为与 tcp 段分开的消息,所以我被卡住了。

发送代码如下:

def sendFile(self,filePath):
    try:
        f = open(filePath, 'rb')
        print 'file opened'
        for soc in self.allClients.keys():
            try:
                f = open(filePath, 'rb')
            except:
                print "File does not exist"
            print 'Sending File: ' + filePath
            l = f.read(1024)
            while (l):
                print 'Sending...'
                soc.send(l)
                l = f.read(1024)
            soc.send('end')
            f.close()
            print 'File sent'                
    except:
        print "File does not exist"

接收代码如下所示:

 def receiveFile(self, ext, clientsoc):   
    f = open('receivedFile' + ext,'wb')

    print "Receiving File..."
    l = clientsoc.recv(1024)
    while(l):
        print "Receiving..."
        if (l is not 'end'):
            f.write(l)   
            print l + '\n'
            l = clientsoc.recv(1024)
        else:
            break
    f.close()
    print "Received Fileeeeeooooo"

更奇怪的是,当我在对等程序之外使用此代码时,它仍然有效。任何帮助将不胜感激,我已经为此苦苦挣扎了两天。

【问题讨论】:

  • 解决此问题的更典型方法是在开始发送文件之前发送文件的长度。这样,就不用担心您发送的文件是否包含文件结束信号。

标签: python sockets tcp sendfile


【解决方案1】:

首先,不能将字符串与isis not进行比较:

>>> a = "he"
>>> a + "llo" is "hello"
False

其次,TCP 是一种流协议。 recv 达到 1024 字节,但可能更少,如果您从服务器发送两份,它们可以合并为一个 recv。所以l 不太可能是"end",而是“文件结尾的最后一个字节”。如果您检查"end",则不允许"end" 在文件中。最好的解决方案是先发送文件的长度,然后发送和接收length字节。

PS:你可能想在服务器端使用sendall

【讨论】:

  • 如果有时数据没有通过“线路”传输会发生什么,recv 是阻塞调用吗?我的意思是它什么时候会返回0
  • 是的,这正是正在发生的事情,“结束”只是附加到最后一个“l”段。谢谢,我会试试看!
【解决方案2】:

首先发送文件大小!

新代码如下所示。

发送代码:

def sendFileOrImage(self,path):

    name, ext = os.path.splitext(path)
    filesize = str(os.path.getsize(path))
    message = filesize + ',' + ext
    print 'message'
    for client in self.allClients.keys():
        client.send(message)
        self.sendFile(path)

def sendFile(self,filePath):
    try:
        f = open(filePath, 'rb')
    except:
        print "File does not exist"
    print 'Sending File: ' + filePathty
    for soc in self.allClients.keys():
        l = f.read(1024)
        while (l):
            print 'Sending...'
            soc.send(l)
            l = f.read(1024)
        f.close()
        print 'File sent'

接收代码:

def receiveFile(self,ext, filesize, clientsoc):   
    total = 0
    f = open('receivedFile' + ext,'wb')

    print "Receiving File..."
    l = clientsoc.recv(1024)
    total = len(l)
    while(l):
        print "Receiving..."

        f.write(l) 
        if (str(total) != filesize):
            print 'trying to receive'
            l = clientsoc.recv(1024)
            total = total + len(l)
        else:
            break
    f.close()
    print "Received Fileeeeeooooo"

感谢大家的帮助!

【讨论】:

    【解决方案3】:

    您的接收代码有效,但仍有一个问题需要您快速解决。如果您的文件大小低于 1024,您的套接字将一直监听,为了解决此问题,您需要更改代码,如下所示。

    def receiveFile(self,ext, filesize, clientsoc):   
        total = 0
        f = open('receivedFile' + ext,'wb')
        print("Receiving File...")
        l = clientsoc.recv(1024)
        total = len(l)
        while(l):
            print("Receiving...")
            f.write(l) 
            if (str(total) != filesize):
                print 'trying to receive'
                l = clientsoc.recv(1024)
                total = total + len(l)
            if(int(total)>= int(filesize)):
                break
        f.close()
        print("Received Fileeeeeoooo")
    

    【讨论】:

      猜你喜欢
      • 2020-01-10
      • 1970-01-01
      • 2012-04-06
      • 2015-02-04
      • 2013-01-04
      • 2016-07-13
      • 2013-10-04
      • 2011-05-20
      • 2014-12-15
      相关资源
      最近更新 更多