Комната чата отправки / получения Python не работает (обновлено) - PullRequest
0 голосов
/ 17 февраля 2019

Я задал вопрос о коде моего сервера клиенту, потому что у меня было много проблем, и кто-то сказал мне, что решение моих проблем состояло в том, чтобы сделать одноранговый чат, который я сейчас сделал.

Server.py

import socket, threading

host = "127.0.0.1"
port = 4000
s = socket.socket()
s.bind((host,port))
s.listen(5)
client_sockets = []
users = []
print("Listening")

def handle_client(conn):
    while True:
        try:
            data = conn.recv(512)
            for x in client_sockets:
                try:
                    x.send(data)
                except Exception as e:
                    print(e)
        except:
            pass

while True:
    conn,addr = s.accept()
    client_sockets.append(conn)
    print("Connections from", addr[0], "on port",addr[1])
    threading.Thread(target = handle_client,args = (conn,)).start()

Client.py

import socket,threading

host = "127.0.0.1"
port = 4000
s = socket.socket()
s.connect((host,port))

def echo_data(sock):
   while True:
      try:
         data = sock.recv(512)
         print(data)
      except:
         pass

while True:
   threading.Thread(target=echo_data,args=(s,)).start()
   msg = input("Enter your message : ")
   s.send(msg.encode())

Проблема заключается в том, что, когда я запускаю клиент и пытаюсь поговорить с другим клиентом, сообщение не отправляется, если другоеклиент нажимает ввод, а также это подводит меня ко второй проблеме, когда клиенты отправляют друг другу сообщения, полученные в следующем формате:

b'hi'Enter your message :

Это ссылкана мой предыдущий вопрос

1 Ответ

0 голосов
/ 18 февраля 2019

Я начну с общих проблем, не связанных напрямую с вопросом:

  • except: pass - это, как правило, плохая идея, особенно когда что-то идет не так, потому что это скрывает потенциально полезные сообщения.Это разрешено языком, но никогда не должно существовать в реальном коде
  • в client.py, вы запускаете поток получения для каждого сообщения, в то время как вам нужен только один поток для всего клиента.Вы должны начать поток вне цикла:

    threading.Thread(target=echo_data,args=(s,)).start()
    while True:
       msg = input("Enter your message : ")
       s.send(msg.encode())
    

Теперь по вопросам:

  • сообщение не получаетотправлено, если другой клиент не нажал, введите

    Это может быть вызвано IDE.В частности, известно, что IDLE плохо работает с многопоточными сценариями.Если вы правильно используете один отдельный поток приема и запускаете скрипт из командной строки (python client.py), он должен работать правильно

  • сообщения получаются в следующем формате: b'hi'Enter your message

    sock.recv(sz) возвращает байтовую строку.Вам нужно декодировать его, чтобы преобразовать в строку Unicode Python 3:

     data = sock.recv(512)
     print(data.decode())
    

Но это еще не все.Это хорошо для тестов, но вы должны, по крайней мере, разрешить клиентам отключаться от сервера и, когда они это делают, удалить их из client_sockets.И часто отправитель не отправляет обратно сообщение.Таким образом, вы можете улучшить цикл server.py:

while True:
    try:
        data = conn.recv(512)
        for x in client_sockets:
            if x != conn:         # do not echo to sender
                x.send(data)
    except Exception as e:        # problem in connection: exit the loop
        print(e)
        break
# clear the connection
conn.close()
client_sockets.remove(conn)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...