成功传输后,才关闭Greenlet中的TCP套接字

时间:2015-03-15 21:51:47

标签: python sockets asynchronous gevent

我正在尝试在成功传输所有数据后关闭我的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 个答案:

答案 0 :(得分:0)

在您的服务器代码中,您回显到发件人的每一行(socket.sendall(l))。但是,在您的客户端代码中,只要您发送了所有数据,您就会关闭连接,这样您的服务器就不会再发送数据。如果你注释掉socket.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()