简体   繁体   English

python的线程化TCP套接字

[英]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 . 我是python编程和套接字的新手,所以我从http://docs.python.org/2/library/socketserver.html处的异步(线程)SocketServer示例开始。

The example for the ThreadingMixIn class works well, however I have 2 questions for the experts: ThreadingMixIn类的示例运行良好,但是对于专家我有两个问题:

  • 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. 第二个问题是关于handle方法。 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. 我尝试从客户端使用sendall发送2条连续消息,但是第二次发送失败...看来,实际上handle方法等待第一条消息,然后终止。 I had to add a 'while 1:' for getting to work. 我必须添加“ while 1:”才能开始工作。

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. 如您所见,每次运行客户端代码时,即使先前的套接字已关闭,也会创建一个新线程……或者至少,threading.current_thread()返回一个新的ID。 How can I check that the previous thread is stopped? 如何检查上一个线程是否已停止?

In regards to @luka's answer; 关于@luka的答案; Dietrich is correct in that using threads this way is fine. Dietrich是正确的,因为以这种方式使用线程很好。 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. 是的,您只能在给定时间执行一条python指令,但是套接字无论如何通常都是I / O绑定的,所以一切都很好。

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. 知道线程已死亡的最简单方法不是直接从python中获取,因为这与您使用的接口有些相似。 Instead I would look to the operating system which can provide this information. 相反,我会看一下可以提供此信息的操作系统。 On Linux, just execute the pstree command. 在Linux上,只需执行pstree命令。 Your thread count should be displayed as something like <thread count>*[{process name}] , where thread count is the count of your threads. 您的线程数应显示为<thread count>*[{process name}] ,其中线程数是您的线程数。

Other methods include having your application print "stating thread", then "ending thread", or using the python debugged (pydb). 其他方法包括让您的应用程序打印“状态线程”,“结束线程”或使用调试的python(pydb)。

In regards to the last point raised by @luka about event driven python, it is kind of premature optimization. 关于@luka关于事件驱动的python的最后一点,这是一种过早的优化。 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. 如果您期望一个巨大的负载,则每个请求的线程派生可能会成为需要解决的瓶颈。

  1. Python is running from single thread so using multiple threads doesn't give you any performance boost if this is your aim. Python是从单线程运行的,因此,如果这是您的目标,那么使用多个线程不会给您带来任何性能提升。 It will likely unecessary spend more memory. 可能会不必要地花费更多的内存。
  2. I recommend using gevent library to abstract parallel execution and handling large number of sockets. 我建议使用gevent库来抽象并行执行和处理大量套接字。

http://www.gevent.org/ http://www.gevent.org/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM