Reputation: 4950
I'm trying here to close my TCP socket only after all data is successfully transferred:
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)
It seems, that socket is closed too soon, as I always receive only first two lines of my login_str
on the other end. If I uncomment gevent.sleep(1)
- everything works as expected. But I doubt that would be the case, if I've tried to send 1000 lines or with the flapping connection, perhaps required timeout would be 2 sec. This is unpredictable and not desirable side effect of async. programming, as far as I see it, so I'm quite sure there must be an easy workaround, which I just can't find?
EDIT
For the sake of completeness I've also added echo server part:
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()
Upvotes: 1
Views: 680
Reputation: 1810
In your server code, you are echoing back to the sender each line that you read (socket.sendall(l)
). However, in your client code, you are closing the connection as soon as you have sent all the data which leaves no chance for your server to send data back. If you comment out socket.sendall(l)
, you will see that you indeed do receive all four lines.
If you do need to send data back, you can modify your client code to wait for server to finish sending all the data:
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()
Upvotes: 1