使用 Python(套接字)创建一个简单的聊天应用程序

问题描述 投票:0回答:3
我正在尝试使用套接字(python)创建一个简单的聊天应用程序。客户端可以向服务器发送消息,服务器只需将消息广播给除发送消息的客户端之外的所有其他客户端。

客户端有两个线程,它们永远运行

send

:发送只是将客户端消息发送到服务器。

receive

:接收服务器发来的消息。

服务器也有两个线程,永远运行

accept_cleint

:接受来自客户端的传入连接。

broadcast_usr

:接受来自客户端的消息并将其广播给所有其他客户端。

但是我得到了错误的输出(请参阅下图)。所有线程都假设始终处于活动状态,但有时客户端可以发送消息,有时却不能。举例来说,Tracey 发送“hi”4 次但未广播,当 John 说“bye”2 次后,其消息被广播 1 次。服务器似乎有一些

thread synchronization

问题,我不确定。请告诉我出了什么问题。 

enter image description here

下面是代码。

chat_client.py

import socket, threading def send(): while True: msg = raw_input('\nMe > ') cli_sock.send(msg) def receive(): while True: sen_name = cli_sock.recv(1024) data = cli_sock.recv(1024) print('\n' + str(sen_name) + ' > ' + str(data)) if __name__ == "__main__": # socket cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # connect HOST = 'localhost' PORT = 5023 cli_sock.connect((HOST, PORT)) print('Connected to remote host...') uname = raw_input('Enter your name to enter the chat > ') cli_sock.send(uname) thread_send = threading.Thread(target = send) thread_send.start() thread_receive = threading.Thread(target = receive) thread_receive.start()

chat_server.py

import socket, threading def accept_client(): while True: #accept cli_sock, cli_add = ser_sock.accept() uname = cli_sock.recv(1024) CONNECTION_LIST.append((uname, cli_sock)) print('%s is now connected' %uname) def broadcast_usr(): while True: for i in range(len(CONNECTION_LIST)): try: data = CONNECTION_LIST[i][1].recv(1024) if data: b_usr(CONNECTION_LIST[i][1], CONNECTION_LIST[i][0], data) except Exception as x: print(x.message) break def b_usr(cs_sock, sen_name, msg): for i in range(len(CONNECTION_LIST)): if (CONNECTION_LIST[i][1] != cs_sock): CONNECTION_LIST[i][1].send(sen_name) CONNECTION_LIST[i][1].send(msg) if __name__ == "__main__": CONNECTION_LIST = [] # socket ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # bind HOST = 'localhost' PORT = 5023 ser_sock.bind((HOST, PORT)) # listen ser_sock.listen(1) print('Chat server started on port : ' + str(PORT)) thread_ac = threading.Thread(target = accept_client) thread_ac.start() thread_bs = threading.Thread(target = broadcast_usr) thread_bs.start()
    
python multithreading sockets synchronization chat
3个回答
1
投票
好吧,我之前在评论中撒了谎,抱歉。问题实际上出在服务器上的

broadcast_usr()

 函数上。它在 
recv()
 方法中阻塞,并阻止除当前选定的用户之外的所有用户在通过 
for
 循环进行时同时讲话。为了解决这个问题,我更改了 server.py 程序,为它接受的每个客户端连接生成一个新的 Broadcast_usr 线程。我希望这有帮助。

import socket, threading def accept_client(): while True: #accept cli_sock, cli_add = ser_sock.accept() uname = cli_sock.recv(1024) CONNECTION_LIST.append((uname, cli_sock)) print('%s is now connected' %uname) thread_client = threading.Thread(target = broadcast_usr, args=[uname, cli_sock]) thread_client.start() def broadcast_usr(uname, cli_sock): while True: try: data = cli_sock.recv(1024) if data: print "{0} spoke".format(uname) b_usr(cli_sock, uname, data) except Exception as x: print(x.message) break def b_usr(cs_sock, sen_name, msg): for client in CONNECTION_LIST: if client[1] != cs_sock: client[1].send(sen_name) client[1].send(msg) if __name__ == "__main__": CONNECTION_LIST = [] # socket ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # bind HOST = 'localhost' PORT = 5023 ser_sock.bind((HOST, PORT)) # listen ser_sock.listen(1) print('Chat server started on port : ' + str(PORT)) thread_ac = threading.Thread(target = accept_client) thread_ac.start() #thread_bs = threading.Thread(target = broadcast_usr) #thread_bs.start()
    

1
投票
我试图绕过你说的错误@Atinesh。客户端将被询问一次用户名,并且该“uname”将包含在要发送的数据中。看看我对“

send”函数做了什么。

为了更容易可视化,我在所有收到的消息中添加了“ ”。

import socket, threading def send(uname): while True: msg = raw_input('\nMe > ') data = uname + '>' + msg cli_sock.send(data) def receive(): while True: data = cli_sock.recv(1024) print('\t'+ str(data)) if __name__ == "__main__": # socket cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # connect HOST = 'localhost' PORT = 5023 uname = raw_input('Enter your name to enter the chat > ') cli_sock.connect((HOST, PORT)) print('Connected to remote host...') thread_send = threading.Thread(target = send,args=[uname]) thread_send.start() thread_receive = threading.Thread(target = receive) thread_receive.start()

您还必须相应地修改您的服务器代码。

服务器.py

import socket, threading def accept_client(): while True: #accept cli_sock, cli_add = ser_sock.accept() CONNECTION_LIST.append(cli_sock) thread_client = threading.Thread(target = broadcast_usr, args=[cli_sock]) thread_client.start() def broadcast_usr(cli_sock): while True: try: data = cli_sock.recv(1024) if data: b_usr(cli_sock, data) except Exception as x: print(x.message) break def b_usr(cs_sock, msg): for client in CONNECTION_LIST: if client != cs_sock: client.send(msg) if __name__ == "__main__": CONNECTION_LIST = [] # socket ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # bind HOST = 'localhost' PORT = 5023 ser_sock.bind((HOST, PORT)) # listen ser_sock.listen(1) print('Chat server started on port : ' + str(PORT)) thread_ac = threading.Thread(target = accept_client) thread_ac.start()

服务器端发生的变化是:连接的用户和说话的用户不再可见。我不知道如果您的目的是连接客户,这是否意味着那么多。也许如果你想通过服务器严格监控客户端,可能还有另一种方法。


0
投票
您似乎已经开始使用套接字和线程为简单的聊天服务器编写 Python 脚本。以下是代码的作用:

    它定义了一个函数
  1. accept_client()
    ,不断接受传入的客户端连接,将它们添加到名为 
    CONNECTION_LIST
     的列表中,并启动一个新线程来处理每个客户端。
  2. 它定义了一个函数
  3. broadcast_usr(cli_sock)
    ,它不断地从客户端套接字接收消息并将它们广播到所有其他连接的客户端。
  4. 它定义了一个函数
  5. b_usr(cs_sock, msg)
    ,从客户端套接字 
    msg
     向所有其他连接的客户端发送消息 
    cs_sock
  6. 最后,它初始化一个空列表
  7. CONNECTION_LIST
    ,创建一个 TCP/IP 套接字,将其绑定到本地主机和端口 5023,并开始侦听传入连接。
© www.soinside.com 2019 - 2024. All rights reserved.