daftendireckt
daftendireckt

Reputation: 35

threaded TCP sockets with python

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:

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

Answers (2)

Clarus
Clarus

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

Luka Rahne
Luka Rahne

Reputation: 10447

  1. Python is running from single thread so using multiple threads doesn’t give you any performance boost if this is your aim. It will likely unecessary spend more memory.
  2. I recommend using gevent library to abstract parallel execution and handling large number of sockets.

http://www.gevent.org/

Upvotes: 0

Related Questions