Python отправляет неполные данные через сокет - PullRequest
1 голос
/ 31 мая 2010

У меня есть скрипт сервера сокетов,

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, но сжатые данные тоже не отправляются полностью, потому что я постоянно получаю ошибки заголовка, которые, как я смог найти, объясняются тем, что сжатая строка была неполной.

Ответы [ 2 ]

6 голосов
/ 31 мая 2010

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

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

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

0 голосов
/ 28 августа 2012

Используйте модуль pickle для сериализации объекта в гнездо и загрузки его на другую сторону. Что-то вроде:

    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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...