python停止多线程回显服务器

时间:2014-12-19 13:51:04

标签: python multithreading

我尝试创建多线程echo服务器:

echomain.py:

#!/usr/bin/python
from echoserver import echoserver 
server = echoserver()

print server.isRunning()
print server.port()
server.start()
print "Main program continues..."\\This part is not displayed(((

echoserver.py:

#!/usr/bin/python
import threading
import socket

class connection(threading.Thread):
    def __init__(self, sock, addr):
        self.sock = sock
        self.addr = addr
        threading.Thread.__init__(self)
    def run (self):
        while True:
            buffer = self.sock.recv(1024)
            if buffer == "disconnect\r\n":
                self.sock.send("bye")
                break
            elif buffer:
                self.sock.send(buffer)
        self.sock.close()

class echoserver(object):
    def __init__(self, port=12119):
        self.running = False
        self._port = port
        self._socket = None

    def isRunning(self):
        return self.running

    def port(self):
        return self._port

    def start(self):
        self.running = True
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._socket.bind(("0.0.0.0", self.port()))
        self._socket.listen(5)
        while True:
            conn, addr = self._socket.accept()
            connection(conn, addr).start()

    def stop(self):
        self._socket.close()
        print "Server is closed..." 

有人可以帮助我如何将echoserver类作为一个线程启动,以便它与主程序同时运行,这样我可以在echomain.py部分使用stop()方法停止它吗?

2 个答案:

答案 0 :(得分:1)

更改您的跑步者计划以将服务器作为线程运行:

<强> echomain.py

#!/usr/bin/python
from echoserver import echoserver
from threading import Thread
import time
server = echoserver()

print server.isRunning()
print server.port()
# server.start()
# run server in a different thread
serverThread = Thread(target=server.start)
serverThread.start()
print "main - server started"
# wait ten seconds before stopping
time.sleep(10)
server.stop()
print "main - server stopped"
print "Main program continues..."

此示例仅在10秒后停止服务器。

答案 1 :(得分:1)

最简单的方法是让你的echoserver本身成为Reut Sharabani提出的线程,但是恕我直言,你也应该实现一个正确的stop()方法,确保所有孩子都已经结束。

以下是我的脚本实现:

#!/usr/bin/python
import threading
import socket

class connection(threading.Thread):
    def __init__(self, sock, addr, parent):
        self.sock = sock
        self.addr = addr
        self.parent = parent
        threading.Thread.__init__(self)
        self.sock.settimeout(None)
        self.closed = False # will be set to True on thread end
    def run (self):
        while not self.parent._stopped:
            buffer = self.sock.recv(1024)
            if buffer == "disconnected\r\n":
                self.sock.send("bye")
                break
            elif buffer:
                self.sock.send(buffer)
        self.sock.close()
        self.closed = True

class echoserver(threading.Thread):
    def __init__(self, port=12119):
        threading.Thread.__init__(self)
        self.running = False
        self._port = port
        self._socket = None
        self._stopped = False
        self._conns = [] # list of active connections

    def isRunning(self):
        return self.running

    def port(self):
        return self._port

    def run(self):
        self.running = True
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._socket.bind(("0.0.0.0", self.port()))
        self._socket.listen(5)
        self._socket.settimeout(5) # use a timeout to respond to stop()
        while not self._stopped:
            try:
                conn, addr = self._socket.accept()
                c = connection(conn, addr, self)
                self._conns.append(c) # add child the the list
                c.start()
            except Exception as e:
                # print e # in debug
                pass
            self._conns = self.child_list() # remove closed child from list
        self._socket.close()
        print "Server is closing..."
        for connect in self._conns: # join active children
            connect.join()
        print "Server is closed"           

    def stop(self):
        self._stopped = True

    def child_list(self):
        l = []
        for conn in self._conns:
            if conn.closed:
                conn.join()
            else:
                l.append(conn)
        return l

备注:

  • 你只是这样使用它:

    serv=echoserver()
    serv.start()
    ... # sleep of do anything you want
    serv.stop()
    
  • 如果在调用stop()时没有连接处于活动状态,则在接受超时结束时所有停止并且您得到:

    Server is closing...
    Server is closed
    
  • 如果在调用stop()时至少有一个连接处于活动状态,则在接受超时结束时仅获得Server is closing...。然后对于每个连接,它将在收到数据包后立即结束,并由echoserver加入。然后,当所有连接都结束时,您将获得Server is closed并且echoserver线程将终止

  • 这意味着您只需要在主线程中执行

    serv.stop()
    serv.join()
    

确保所有其他线程都正确终止,并且所有套接字都已关闭