代码之家  ›  专栏  ›  技术社区  ›  tipu

python通过套接字发送不完整的数据

  •  0
  • tipu  · 技术社区  · 15 年前

    我有这个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()
    

    这个接收器,

    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 回复  |  直到 13 年前
        1
  •  5
  •   Alex Martelli    15 年前

    socket.recv(N) 不保证会收到确切的n个字节:相反,n只是 最大限度 一口就能接收到的字节数(根据文档的建议,为了提高效率,最好是4096的小倍数)。

    你需要“不断地接收”(循环和积累),直到你拥有你想要的所有字节(而且看起来你的协议没有传达出关键的价值:你 必须使其显式化,无论是在传输结束时使用前缀长度还是终止符,都无法从流套接字中隐式提取它)。

    同样用于发送,尽管在这种情况下,您可以使用 socket.sendall 它代表你做了必要的循环。

        2
  •  0
  •   Masood_mj    13 年前

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