发送/接收Python聊天室不起作用(已更新)

时间:2019-02-17 18:03:46

标签: python python-3.x sockets tcp

我问了一个有关服务器到客户端代码的问题,因为我遇到了很多问题,有人告诉我,解决我遇到的问题的方法是进行对等聊天,现在已经完成了。

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 :

This is the link to my previous question

1 个答案:

答案 0 :(得分:1)

我将从与该问题不直接相关的一般问题入手:

  • 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)返回一个字节字符串。您需要对其进行解码以将其转换为Python 3 unicode字符串:

     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)