Reputation: 245
In the code shown below I am using the blocking call to receive 50 bytes of data from socket and echo it back.But what is happening is that the code stuck after receiving one byte.In the telnet running on another command prompt the connection still shows as connected. What might be missing from this ?
import socket
import sys
host = ''
port = 8888
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
print 'Socket Bind Complete'
s.listen(10)
print 'Now Listening'
while 1:
conn, adr = s.accept()
print 'connected with' + adr[0] + ':' + str(adr[1])
data = conn.recv(50)
print data
if not data:
break
conn.sendall(data)
conn.close()
s.close()
Upvotes: 1
Views: 1318
Reputation: 365915
The problem is that you're accept
ing a new connection each time through the loop, and only receiving from that connection once. The next time through the loop, your forget about that connection and accept
a new one, which blocks until someone else connects.
If you just want to handle a single connection and quit, just move the accept
outside the loop:
conn, adr = s.accept()
print 'connected with' + adr[0] + ':' + str(adr[1])
while True:
data = conn.recv(50)
print data
if not data:
break
conn.sendall(data)
conn.close()
s.close()
If you want to handle one connection at a time, but then wait for a new connection after you finish with the first, add an outer loop.
while True:
conn, adr = s.accept()
print 'connected with' + adr[0] + ':' + str(adr[1])
while True:
data = conn.recv(50)
print data
if not data:
break
conn.sendall(data)
conn.close()
s.close()
If you want to handle more than one connection at a time, as most servers do, you need some sort of asynchronous mechanism—select
and nonblocking sockets, gevent
, threads, whatever. For example:
def handle_client(conn, addr):
print 'connected with' + adr[0] + ':' + str(adr[1])
while True:
data = conn.recv(50)
print data
if not data:
break
conn.sendall(data)
conn.close()
client_threads = []
try:
while True:
conn, adr = s.accept()
client_thread = threading.Thread(target=handle_client, args=[conn, addr])
client_thread.start()
client_threads.append(client_thread)
finally:
s.close()
for client_thread in client_threads:
client_thread.join()
In any of these designs, you're probably better off using a with
statement instead of explicit close
calls and/or try
/finally
.
Upvotes: 1