I am trying to send a file over a tcp socket in a peer to peer chat system coded in python. The receiving socket seems not to know that there is no more file to receive. The only way I can get the receiving socket to not anticipate the data that isn't coming is by closing the sending socket (using socket.shutdown(socket.SHUT_WR)). However, closing the sending socket is not an option because I need that socket to send other messages. I fisrt tried allocating a new port for file sending/receiving and failed. Now, I have tried creating an end of file "signal" but it does not get recognized on the receiving end as a message separate from the tcp segment, so I am stuck.
我试图通过在python中编码的对等聊天系统中的tcp套接字发送文件。接收套接字似乎不知道没有更多文件可以接收。我可以让接收套接字不预期未来的数据的唯一方法是关闭发送套接字(使用socket.shutdown(socket.SHUT_WR))。但是,关闭发送套接字不是一个选项,因为我需要该套接字来发送其他消息。我fisrt尝试为文件发送/接收分配一个新端口并失败。现在,我已经尝试创建一个文件结尾“signal”但它不会在接收端被识别为与tcp段分开的消息,所以我被卡住了。
The sending code looks like this:
发送代码如下所示:
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"
the receiving code looks like this:
接收代码如下所示:
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"
Even more strange, this code works when I am using it outside of my peer programme. Any help would be greatly appreciated, I have been struggling with this for two days now.
更奇怪的是,当我在同行程序之外使用它时,此代码可以正常工作。任何帮助将不胜感激,我已经为此奋斗了两天了。
2 个解决方案
#1
First of all, you must not compare strings with is
or is not
:
首先,您不能将字符串与是或否进行比较:
>>> a = "he"
>>> a + "llo" is "hello"
False
Second, TCP is a streaming protocol. recv
is getting up to 1024 bytes, but could be less, and if you send two pieces from your server, they can be merged into one recv
. So l
is not likely to be "end"
but "last bytes of the file's end". And if you check for "end"
, "end"
is not allowed to be in the file. Best solution is to send the length of the file first, and then send and recv length
bytes.
其次,TCP是一种流媒体协议。 recv最多可达1024个字节,但可能更少,如果从服务器发送两个,它们可以合并为一个recv。所以我不太可能是“结束”而是“文件结束的最后一个字节”。如果您检查“结束”,则不允许“结束”在文件中。最佳解决方案是首先发送文件的长度,然后发送和recv长度字节。
PS: you probably want to use sendall
at the server side.
PS:你可能想在服务器端使用sendall。
#2
Sending the file size first worked!!
发送文件大小首先工作!!
New code looks like this.
新代码看起来像这样。
Sending code:
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'
Receiving code:
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"
Thanks everyone for the help!
谢谢大家的帮助!
#1
First of all, you must not compare strings with is
or is not
:
首先,您不能将字符串与是或否进行比较:
>>> a = "he"
>>> a + "llo" is "hello"
False
Second, TCP is a streaming protocol. recv
is getting up to 1024 bytes, but could be less, and if you send two pieces from your server, they can be merged into one recv
. So l
is not likely to be "end"
but "last bytes of the file's end". And if you check for "end"
, "end"
is not allowed to be in the file. Best solution is to send the length of the file first, and then send and recv length
bytes.
其次,TCP是一种流媒体协议。 recv最多可达1024个字节,但可能更少,如果从服务器发送两个,它们可以合并为一个recv。所以我不太可能是“结束”而是“文件结束的最后一个字节”。如果您检查“结束”,则不允许“结束”在文件中。最佳解决方案是首先发送文件的长度,然后发送和recv长度字节。
PS: you probably want to use sendall
at the server side.
PS:你可能想在服务器端使用sendall。
#2
Sending the file size first worked!!
发送文件大小首先工作!!
New code looks like this.
新代码看起来像这样。
Sending code:
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'
Receiving code:
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"
Thanks everyone for the help!
谢谢大家的帮助!