Мне было интересно, может ли кто-нибудь помочь мне. Итак, я делаю чат на питоне с сокетами и использую потоки, чтобы клиент мог одновременно слушать и отправлять сообщения.
Но у меня проблема: когда клиент получает сообщение, он искажает ввод (он печатает полученное сообщение как ввод пользователя).
Поэтому мне было интересно, не было ли способов отменить ввод при получении сообщения, распечатать полученное сообщение, а затем снова запросить ввод
Или можно что-то сделать с нитями?
Если вам нужно, вот мой код потока:
recieve_thread = threading.Thread(target=recieve)
recieve_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
А вот бит кода ввода и вывода сообщения
message = input("Me: ")
message = formatMess(nickname, message)
client.send(message.encode('ascii'))
message = client.recv(1024).decode('ascii')
print(message)
Спасибо
Уже сделал это
Поэтому, когда клиент хочет отправить сообщение, он отправляет его на сервер, который затем передает его всем подключенным к нему клиентам.
Моя проблема действительно связана с вводом и печатью, когда сообщение получено, я должен его распечатать, в то же время позволяя пользователю писать
Не могли бы вы просто поделиться кодом, чтобы мы могли лучше понять вашу проблему?
Конечно мой плохой, обновляю его
В идеале иметь отдельное окно для ввода и вывода, как во всех приложениях, подобных мессенджерам с графическим интерфейсом.
Основываясь на этом ответе stackoverflow , вы можете использовать следующее для печати сообщений над строкой ввода.
import threading
LOCK = threading.Lock() # lock to avoid mixing messages while printing
def print_message(message):
""" print the received message line by line above the input line"""
with LOCK:
for line in str.splitlines(message):
print(
"\u001B[s" # Save current cursor position
"\u001B[A" # Move cursor up one line
"\u001B[999D" # Move cursor to beginning of line
"\u001B[S" # Scroll up/pan window down 1 line
"\u001B[L", # Insert new line
end = "")
print(line, end = "") # Print message line
print("\u001B[u", end = "") # Move back to the former cursor position
print("", end = "", flush=True) # Flush message
В качестве иллюстрации, вот прием поддельного сообщения:
import threading
import time
def receive():
i = 0
while True:
time.sleep(2)
message = "hello \n\t" + str(i)
i +=1
print_message(message=message)
def write():
while True:
x = input('>')
receive_thread = threading.Thread(target=receive)
receive_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
Большое спасибо, мне было интересно, а нет ли более аккуратных способов сделать это? может быть, с очередями и потоками idk?
Пожалуйста. К сожалению, я не вижу другого способа сделать это.
@Beni Я рефакторил код. Я надеюсь, что это яснее.
Да, спасибо большое, очень помогло, еще раз воспользуюсь
Вам нужно создать две программы сокетов: одну для клиентского сокета, а другую для сокета сервера. Сначала вам нужно подключить всех своих клиентов к серверу, а затем начать связь между клиентом и клиентом через сервер.