代码之家  ›  专栏  ›  技术社区  ›  NarÅ«nasK

仅在成功传输后关闭Greenlet中的TCP套接字

  •  1
  • NarÅ«nasK  · 技术社区  · 10 年前

    只有在成功传输所有数据后,我才尝试关闭TCP套接字:

    from gevent import monkey; monkey.patch_all()
    import gevent
    import socket
    
    host = "127.0.0.1"
    port = 8888
    
    line_term = "\r\n"
    
    login_str = ["Action: Login",
                 "ActionID: 1",
                 "Username: ami",
                 "Secret: password",
                 ]
    
    def login(login_str):
        conn = socket.create_connection([host, port])
    
        for i in login_str:
            conn.sendall(i + line_term)
    
        conn.send(line_term)
        # Everything works, as soon as I uncomment this line below :/
        # gevent.sleep(1)
        conn.close()
    
    g1 = gevent.spawn(login, login_str)
    g1.join(timeout=2)
    

    看来,插座关闭得太快了,因为我总是只收到我的前两行 login_str 另一端。如果取消注释 gevent.sleep(1) -一切都按预期进行。但我怀疑,如果我尝试发送1000条线路或使用扇动连接,可能需要的超时时间为2秒。这是不可预测的,也是异步的不可取的副作用。编程,就我所见,所以我很确定一定有一个简单的解决方法,我就是找不到?

    编辑

    为了完整起见,我还添加了echo服务器部分:

    from gevent.server import StreamServer
    
    def connection_handler(socket, address):
        for l in socket.makefile('r'):
            print str(len(l)) + ' : ' + l
            socket.sendall(l)
    
    
    if __name__ == '__main__':
        server = StreamServer(('0.0.0.0', 8888), connection_handler)
        server.serve_forever()
    
    1 回复  |  直到 10 年前
        1
  •  1
  •   Mansour    10 年前

    在你的服务器代码中,你读到的每一行都会回显给发送者( socket.sendall(l) ). 然而,在您的客户端代码中,您在发送完所有数据后立即关闭连接,这样服务器就没有机会再发送数据了。如果你发表意见 套接字.sendall(l) ,您将看到您确实收到了所有四行。

    如果您确实需要发送数据,您可以修改客户端代码以等待服务器完成发送所有数据:

    def login(login_str):
        conn = socket.create_connection([host, port])
    
        for i in login_str:
            conn.sendall(i + line_term)
    
        conn.send(line_term)
    
        # Wait until the other end has finished sending data
    
        while conn.recv(1024):
          pass
    
        # Everything works, as soon as I uncomment this line below :/
        # gevent.sleep(1)
        conn.close()