在线程模块python中停止服务器程序

时间:2014-10-14 13:34:15

标签: python multithreading sockets

我在python中编写了一个简单的信息服务器,它回复了3个不同的命令。我必须使用线程模块处理多个客户端,因此处理多个客户端的任何其他方法都不会。每当客户发送' EXIT'到服务器,服务器程序应该退出执行。我以为我可以通过关闭处理客户端的线程内的连接和套接字来实现这一点。当我这样做时,服务器在收到'退出'后继续运行。当下一个客户端尝试连接时崩溃,出现以下错误:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 530, in __bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 483, in run
    self.__target(*self.__args, **self.__kwargs)
  File "info_mult_thread.py", line 69, in handle_client
    s.shutdown(socket.SHUT_RDWR)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 222, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 57] Socket is not connected

这是我的代码:

import socket
import time

from threading import Thread

TCP_HOST = 'localhost'
TCP_PORT = 1997
BUFFER_SIZE = 1024


# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# bind the socket to the server
s.bind((TCP_HOST, TCP_PORT))

# put socket into server mode, this means listen for incoming connections
s.listen(10)


def handle_client(connection_input, client_address_input):
    """ Will handle the requests of the client
    :param connection_input: Connection with the client
    :param client_address_input: Address of the client
    :return: No return value
    """
    complete_command = False
    command = ""

    while True:
        # wait 10 seconds for data from client, otherwise disconnect
        connection_input.settimeout(10.0)

        try:
            data = connection_input.recv(BUFFER_SIZE)

        except socket.timeout:
                # client is idle, close the connection
                connection_input.close()
                break

        else:
            # client has closed the connection
            if not data:
                break

            # add the data to the command
            command += data

            # check whether the command is complete or not
            if command.endswith("\n"):
                complete_command = True
                command = command.rstrip('\r\n')

            if complete_command:
                # full command entered
                if command == 'IP':
                    # client wants his ip address
                    client_ip, client_port = client_address_input
                    connection_input.send(client_ip)

                elif command == 'TIME':
                    # client wants the server-time
                    connection_input.send(time.ctime())

                elif command == 'EXIT':
                    # stop the program
                    connection_input.close()
                    s.shutdown(socket.SHUT_RDWR)
                    s.close()

                else:
                    # command is not supported
                    connection_input.send("The command you've entered is not supported")

                complete_command = False
                command = ""

try:
    while True:
        # wait for a connection
        connection, client_address = s.accept()

        # start a thread to handle the client
        t = Thread(target=handle_client, args=(connection, client_address))
        t.start()

finally:
    connection.close()

1 个答案:

答案 0 :(得分:0)

这有点像黑客,但你可以在调用s.close()之前与服务器建立本地连接,这将保证s.accept()立即引发异常:

def handle_client(connection_input, client_address_input):
    """ Will handle the requests of the client
    :param connection_input: Connection with the client
    :param client_address_input: Address of the client
    :return: No return value
    """
    <snip>
    while True:
        <snip>

                elif command == 'EXIT':

                    connection_input.close()
                    # Make a local connection, then close the socket
                    socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((TCP_HOST, TCP_PORT))
                    s.close()
                    break # Break out of the while loop here.


try:
    while True:
        # this will never block, because of select.select
        connection, client_address = s.accept()

        # start a thread to handle the client
        t = Thread(target=handle_client, args=(connection, client_address))
        t.start()
except socket.error:
    print("Shutting down")

finally:
    connection.close()