2010-05-31 6 views
0

J'ai ce script serveur socket,python envoyer des données incomplètes sur socket

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() 

Et ce récepteur,

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)) 

J'envoie des chaînes au récepteur qui sont des centaines de kilo-octets. Je finis par n'en recevoir qu'une partie. Y a-t-il un moyen de réparer cela pour que toute la chaîne soit envoyée?

Modifier: La chaîne que j'essaie d'envoyer est en réalité 418437 caractères. Mais voici l'idée .. J'essaie d'envoyer la représentation sous forme de chaîne d'un ensemble, en utilisant str (set), donc je peux réassembler l'ensemble en utilisant eval. Est-ce qu'il y a un moyen que je peux obtenir le socket pour envoyer les données complètes ou le compresser assez pour que le socket puisse l'envoyer immédiatement? J'ai essayé d'utiliser zlib, mais les données compressées ne m'envoient pas complètement non plus parce que je reçois à plusieurs reprises des erreurs d'en-tête qui, d'après ce que j'ai pu trouver, est parce que la chaîne comprimée était incomplète.

Répondre

5

socket.recv(N) ne garantit pas exactement N octets seront reçues: plutôt, N est que le nombre maximum d'octets qui peut être reçue d'un trait (et pour l'efficacité, il devrait idéalement être un petit multiple de 4096, comme les docs suggèrent). Vous aurez besoin de "continuer à recevoir" (en boucle et en accumulant) jusqu'à ce que vous ayez tous les octets que vous désirez (et il semble que votre protocole ne communique pas cette valeur cruciale: vous devrez le rendre explicite, soit avec une longueur de préfixe soit un terminateur à la fin de la transmission, il n'y a aucun moyen de l'extraire implicitement de la socket du flux).

De même pour l'envoi, bien que pour ce cas, vous pouvez utiliser socket.sendall qui fait la boucle nécessaire en votre nom.

+0

utilisant Sendall, comment puis-je dire quand il est fait envoyer si boucles pour moi – tipu

+0

'socket.sendall' retourne seulement quand il a envoyé toutes les données transmit: autrement dit, quand il renvoie, c'est fini d'envoyer (le fait que tout le looping soit _inside_ c'est exactement la raison pour laquelle vous n'avez pas à vous en soucier ;-). –

+0

Alex, merci pour votre aide! – tipu

0

Utilisez le module pickle pour sérialiser l'objet sur la prise et le charger de l'autre côté. Quelque chose comme:

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() 
Questions connexes