Reputation: 35
I'm new in python programming and socket, so I've started with the example of a asynchronous (threading) SocketServer at http://docs.python.org/2/library/socketserver.html.
The example for the ThreadingMixIn class works well, however I have 2 questions for the experts:
Each new connection creates a new thread, fine. But it seems like the threads never terminate even if the connection on the other side closes as the thread number just increases.
Second question is about the handle method. I've tried to send 2 consecutive messages with sendall from my client, but the second send fails... It appears that in fact the handle method waits for the first message and then terminates. I had to add a 'while 1:' for getting to work.
So to conclude, I've the feeling this example is useless and bad as it just creates a thread only able to receive one single message. If at least it would terminate by itself, but it doesn't seem to be the case for me...
Thanks for your inputs!
Here's the code for the server:
import threading
import SocketServer
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
cur_thread = threading.current_thread()
response = "{}: {}".format(cur_thread.name, data)
self.request.sendall(response)
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
if __name__ == "__main__":
server = ThreadedTCPServer(('localhost', 13009), ThreadedTCPRequestHandler)
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
print "Server loop running in thread:", server_thread.name
raw_input("Hit enter to stop the server")
server.shutdown()
And the client's code:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 13009))
try:
sock.sendall('hello\n')
response = sock.recv(1024)
print "Received: {}".format(response)
# A second 'send' will generate an error on Windows.
# On Mac, no error but the received message is empty as the
# handle method in the server isn't called for each new message
sock.sendall('how are you?')
response = sock.recv(1024)
print "Received: {}".format(response)
except socket.error, (value,message):
print "Error: " + message
finally:
sock.close()
As you can see, each time you run the client's code, a new thread is created even though the previous socket had been closed... or at least, threading.current_thread() returns a new ID. How can I check that the previous thread is stopped?
Upvotes: 0
Views: 1762
Reputation: 2338
In regards to @luka's answer; Dietrich is correct in that using threads this way is fine. Yes, you can only execute one python instruction at a given time, but sockets are typically I/O bound anyway so it is all good.
The easiest way to know a thread is dead is not directly from python as this is somewhat abstracted away with the interface you are using. Instead I would look to the operating system which can provide this information. On Linux, just execute the pstree
command. Your thread count should be displayed as something like <thread count>*[{process name}]
, where thread count is the count of your threads.
Other methods include having your application print "stating thread", then "ending thread", or using the python debugged (pydb).
In regards to the last point raised by @luka about event driven python, it is kind of premature optimization. If you are not expecting a huge load on your application don't worry about it. If you are expecting a huge load then the forking of a thread per request could become a bottleneck that would need to be addressed.
Upvotes: 1
Reputation: 10447
Upvotes: 0