我在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()
答案 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()