如何在不关闭TCP套接字的情况下发送文件结束标志

3
我正在尝试在使用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"

更奇怪的是,当我将此代码用于我的同事程序之外时,它可以正常运行。如果能提供帮助,将不胜感激。我已经为此苦苦挣扎了两天。


1
解决这个问题的更典型方法是在开始发送文件之前发送文件的长度。这样,就不必担心发送的文件是否包含文件结束信号。 - FatalError
3个回答

3

首先,你不能使用isis not来比较字符串:

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

其次,TCP是一种流式协议。 recv 最多获取1024个字节,但可能会少,并且如果您从服务器发送两个片段,它们可以合并为一个 recv 。 因此, l 不太可能是“end”,而是“文件末尾的最后几个字节”。 如果您检查“end”,则不允许在文件中出现“end”。 最佳解决方案是先发送文件长度,然后发送和接收 length 字节。

PS:您可能要在服务器端使用 sendall 。


如果在某个时刻没有数据通过 "wire" 传输,那么会发生什么,recv 是阻塞调用吗?我的意思是它什么时候会返回 0? 如果在“wire”上没有数据传输,recv会阻塞调用吗?我的意思是它会在什么时候返回0 - darxtrix
好的,这里是链接:https://dev59.com/NWQn5IYBdhLWcg3wj3vz - darxtrix
是的,这正是发生的事情,“end”只是被附加到最后一个“l”段上。谢谢,我会尝试一下! - Pelonomi Moiloa

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"

感谢大家的帮助!

0

你的接收代码虽然能够工作,但仍存在一个需要快速解决的问题。如果文件大小小于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")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接