Проблема с синхронизацией потоков
У меня возникла проблема с синхронизацией потоков. Мне нужно сделать так, чтобы код мог завершаться по просьбе пользователя. У меня есть 3 метода в коде: первый - отвечающий за запуск самого сервера, второй - отвечающий за поддержку клиента (получение данных от клиента) и, наконец, третий - отвечающий за запрос у пользователя, хочет ли он закрыть программу. Однако даже если пользователь введёт no или что-либо кроме no, цикл в методе start_server все равно продолжит работать, ибо флаг в нём не обновляется (из за того, что методы с потоками не синхронизированы). А вот как мне синхронизировать их так, чтобы код завершался по зову/просьбе/желанию пользователя, я не знаю. Буду благодарен, если кто-нибудь мне поможет.
Код:
import socket
import threading
class Server:
def __init__(self, host, port):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.flag = True
self.locker = threading.Lock()
def start_server(self):
self.server.bind((self.host, self.port))
self.server.listen(5)
print("Created the server")
while self.flag:
print("Waiting when client connects")
client, _ = self.server.accept()
print("Client connected")
t = threading.Thread(target=self.handle_client, args=(client,))
t.start()
def handle_client(self, client):
while self.flag:
data = client.recv(4096)
data = data.decode("utf-8")
if data:
print(f"Data received: \n{data}")
self.continue_program()
def continue_program(self):
con_inp = input("Continue(yes,no)?: ")
if con_inp.lower() in ["yes", "y"]:
return
else:
self.flag = False
if __name__ == "__main__":
obj_server = Server("127.0.0.1", 8080)
obj_server.start_server()
Ответы (2 шт):
Можно попробовать так Добавлена with self.locker, которая захватывает блокировку self.locker
import socket
import threading
class Server:
def __init__(self, host, port):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.flag = True
self.locker = threading.Lock()
def start_server(self):
self.server.bind((self.host, self.port))
self.server.listen(5)
print("Created the server")
while self.flag:
print("Waiting for client connection")
client, _ = self.server.accept()
print("Client connected")
t = threading.Thread(target=self.handle_client, args=(client,))
t.start()
def handle_client(self, client):
while self.flag:
data = client.recv(4096)
data = data.decode("utf-8")
if data:
print(f"Data received: \n{data}")
self.continue_program()
def continue_program(self):
with self.locker:
con_inp = input("Continue (yes/no)?: ")
if con_inp.lower() in ["yes", "y"]:
return
else:
self.flag = False
if __name__ == "__main__":
obj_server = Server("127.0.0.1", 8080)
obj_server.start_server()
Итак, в общем, я наконец смог решить проблему. Оказывается, нужно было использовать condition в threading. Я немного отредактировал код. Мне помог по факту решить проблему человек с юзернеймом: user207200. Я задал немного иначе вопрос, после чего получил ответ. Я изменил код по аналогии, как и в ответе и, наконец, получил желаемый результат.
Вот изменённый код:
import socket
import threading
class Server:
def __init__(self, host, port):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.flag = True
self.condition = threading.Condition()
def create_server(self):
self.server.bind((self.host, self.port))
self.server.listen(10)
print("Created the server successfully")
def accept_client(self):
while self.flag:
print("Waiting for client connection")
client, _ = self.server.accept()
print("Client connected")
t = threading.Thread(target=self.handle_client, args=(client,))
t.start()
self.condition.acquire()
self.condition.wait()
self.condition.release()
def handle_client(self, client):
while self.flag:
data = client.recv(4096).decode("utf-8")
if data:
print("Data received:\n", data)
else:
break
self.continue_program()
def continue_program(self):
con_inp = input("Continue?: ")
if con_inp.lower().strip() in ["yes", "y"]:
...
else:
self.flag = False
self.condition.acquire()
self.condition.notify_all()
self.condition.release()
return
def run(self):
self.create_server()
self.accept_client()
if __name__ == "__main__":
s = Server("127.0.0.1", 8080)
s.run()