2010-05-31 3 views
0

У меня есть этот скрипт сервера сокета,питон отправки неполных данных через сокет

import SocketServer 
import shelve 
import zlib 

    class MyTCPHandler(SocketServer.BaseRequestHandler): 
     def handle(self): 
      self.words = shelve.open('/home/tipu/Dropbox/dev/workspace/search/words.db', 'r'); 
      self.tweets = shelve.open('/home/tipu/Dropbox/dev/workspace/search/tweets.db', 'r'); 

      param = self.request.recv(1024).strip() 
      try: 
       result = str(self.words[param]) 
      except KeyError: 
       result = "set()" 
      self.request.send(str(result)) 

    if __name__ == "__main__": 
     HOST, PORT = "localhost", 50007 
     SocketServer.TCPServer.allow_reuse_address = True 
     server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler) 
     server.serve_forever() 

И этот приемник,

from django.http import HttpResponse 
from django.template import Context, loader 
import shelve 
import zlib 
import socket 


def index(req, param = ''): 
    HOST = 'localhost'  
    PORT = 50007    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.connect((HOST, PORT)) 
    s.send(param) 
    data = zlib.decompress(s.recv(131072)) 
    s.close() 
    print 'Received', repr(data) 
    t = loader.get_template('index.html') 
    c = Context({ 'foo' : data }) 
    return HttpResponse(t.render(c)) 

Я посылаю строки в приемник, которые в сотни килобайт. Я получаю только часть его. Есть ли способ, который я могу исправить, чтобы отправить всю строку?

Редактировать: Строка, которую я пытаюсь отправить, на самом деле составляет 418437 символов. Но вот идея. Я пытаюсь отправить строковое представление набора, используя str (set), поэтому я могу собрать набор, используя eval. Есть ли способ, чтобы я мог получить сокет, чтобы отправить полные данные или сжать его достаточно, чтобы сокет мог отправить его сразу? Я попытался использовать zlib, но сжатые данные не отправляются полностью либо потому, что я неоднократно получаю ошибки заголовка, которые, из того, что я смог найти, связаны с тем, что сжатая строка была неполной.

ответ

5

socket.recv(N) не гарантирует, что именно будет получено N байт: а, N просто число максимум байт, которые могут быть получены одним глотком (и эффективности она должна в идеале быть небольшим кратным 4096, так как документы предлагают).

Вам нужно будет «продолжать получать» (цикл и накапливать) до тех пор, пока у вас не будет всех желаемых байтов (и похоже, что ваш протокол не сообщает об этом решающем значении: будет должен сделать его явным, либо с длиной префикса, либо с терминатором в конце передачи, нет способа, которым он может быть неявно извлечен из сокета потока).

Аналогичным образом для отправки, хотя для этого случая вы можете использовать socket.sendall, который делает необходимый цикл от вашего имени.

+0

использования SendAll, как я могу сказать, когда это будет сделано, если он посылает петлю для меня – tipu

+0

'socket.sendall' возвращается только тогда, когда он послал все данные, которые вы прошли это, другие слова, когда его возвращается, это делается посылка (тот факт, что весь цикл является _inside_, именно по этой причине вам не нужно беспокоиться об этом ;-). –

+0

Алекс, спасибо за помощь! – tipu

0

Используйте блок рассола, чтобы сериализовать объект на гнездо и загрузить его с другой стороны. Что-то вроде:

pkl_dict= pickle.dumps(THE_SET) 
    mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    mysocket.connect((HOST, PORT)) 

    mysocket.send(pkl_dict) 

    mysocket.close() 
Смежные вопросы