2015-05-08 2 views
2

Я пытаюсь отправить файл через сокет tcp в одноранговой системе чата, закодированной в python. Получающий сокет, похоже, не знает, что больше нет файлов для получения. Единственный способ заставить получающий сокет не предвидеть данные, которые не идут, - это закрыть сокет отправки (используя socket.shutdown (socket.SHUT_WR)). Однако закрытие отправляющего сокета не является вариантом, потому что мне нужен этот сокет для отправки других сообщений. Я попытался выделить новый порт для отправки/получения файла и не удалось. Теперь я попытался создать конец файла «сигнал», но он не распознается на принимающей стороне как сообщение отдельно от сегмента tcp, поэтому я застрял.Как отправить конец файла без закрытия 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

Прежде всего, вы не должны сравнивать строки с is или is not:

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

Во-вторых, TCP является протоколом потоковой передачи. recv получает до 1024 байтов, но может быть меньше, и если вы отправляете две части с вашего сервера, их можно объединить в один recv. Таким образом, l вряд ли будет "end", но «последние байты конца файла». И если вы проверите "end", "end" не может быть в файле. Лучшее решение - сначала отправить длину файла, а затем отправить и вернуть length байтов.

PS: вы, вероятно, захотите использовать sendall со стороны сервера.

+0

Что произойдет, если в какой-то момент данные не передаются по «проводу», «recv» является блокирующим вызовом? Я имею в виду, когда он вернет '0'? – darxtrix

+0

Хорошо, получилось здесь http://stackoverflow.com/questions/16745409/what-does-pythons-socket-recv-return-for-non-blocking-sockets-if-no-data-is-r – darxtrix

+0

Да, это именно то, что происходит, «конец» просто добавляется к последнему «l» сегменту. Спасибо, я попробую! –

0

Отправка файла в первый раз!

Новый код выглядит следующим образом.

Отправив код:

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" 

Спасибо всем за помощь!