如何使用 python socketserver.TCPServer 创建一个多客户端聊天室

How to make a multi-client chat room with python socketserver.TCPServer

我必须使用 Python 中的 serversocket 模块提供的 TCPServer 创建一个多客户端聊天室。如何将 this 变成多客户端服务器并将消息发送给所有其他客户端?

我已经尝试修改示例中的现有代码

...python

import socket
import threading
import socketserver

clientList = []
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):

    def handle(self):
        clientList.append(self.client_address)
        print(clientList)
        print("Client List Length : ",len(clientList))

        while True:
            data = str(self.request.recv(1024), 'ascii')
            if(data.upper() == "EXIT"):
                break
            cur_thread = threading.current_thread()
            response = bytes(data, 'utf_8')
            #self.request.sendall(response)

            for cl in range(1,len(clientList)):
                print("sending to : ",clientList[cl])
                self.request.sendto(response,clientList[cl])

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

def passtime():
    pass
if __name__ == "__main__":

    HOST, PORT = "localhost", 50007


server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
ip, port = server.server_address



# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)

# Exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
while server_thread:
   passtime() 
print("Server loop running in thread:", server_thread.name)

...

我有以下问题: self.request.sendto(request,clientList[cl])

仅将请求发送回发送客户端,而不是客户端列表中的目标客户端。

编辑:我找到了一个解决方案,就在这里:

import socket
import threading
import socketserver
import sys
import select

clientList = []
inbox = []


class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
    clients = []    
    msgSend = 0
    def setup(self):
        clientList.append(self.client_address)
        self.clients = list(dict.fromkeys(clientList))
        print(self.clients)
        print("Client List Length : ",len(self.clients))

    def handle(self):
        while True:
            r,w,e = select.select([self.request],[],[],0.01)
            for rs in r:
                if rs == self.request:
                    data = str(self.request.recv(1024),"ascii")
                    if data:
                        inbox.append(data)
                else:
                    if self.msgSend < len(inbox):
                        for elem in range(self.msgSend, len(inbox)):
                            print("server send :",inbox[elem])
                            self.request.sendall(bytes(inbox[elem],'utf-8'))
                        self.msgSend += 1

            if self.msgSend < len(inbox):
                for elem in range(self.msgSend, len(inbox)):
                    print("server send :",inbox[elem])
                    self.request.sendall(bytes(inbox[elem],'utf-8'))
                self.msgSend += 1

    def finish(self):
        for l in range(len(clientList)):
            if self.client_address == clientList[l]:
                clientList.remove(l)

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

def passtime():
    pass



if __name__ == "__main__":

    HOST, PORT = "localhost", 50007
    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    ip, port = server.server_address

    server_thread = threading.Thread(target=server.serve_forever)


    server_thread.daemon = True
    server_thread.start()
    while server_thread:
       passtime() 


    sys.exit()

我使用 here 的收件箱方法并使用 select.select 我能够检查是否有要读取的输入。

我找到了解决方案,就在这里:

import socket
import threading
import socketserver
import sys
import select

clientList = []
inbox = []


class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
    clients = []    
    msgSend = 0
    def setup(self):
        clientList.append(self.client_address)
        self.clients = list(dict.fromkeys(clientList))
        print(self.clients)
        print("Client List Length : ",len(self.clients))

    def handle(self):
        while True:
            r,w,e = select.select([self.request],[],[],0.01)
            for rs in r:
                if rs == self.request:
                    data = str(self.request.recv(1024),"ascii")
                    if data:
                        inbox.append(data)
                else:
                    if self.msgSend < len(inbox):
                        for elem in range(self.msgSend, len(inbox)):
                            print("server send :",inbox[elem])
                            self.request.sendall(bytes(inbox[elem],'utf-8'))
                        self.msgSend += 1

            if self.msgSend < len(inbox):
                for elem in range(self.msgSend, len(inbox)):
                    print("server send :",inbox[elem])
                    self.request.sendall(bytes(inbox[elem],'utf-8'))
                self.msgSend += 1

    def finish(self):
        for l in range(len(clientList)):
            if self.client_address == clientList[l]:
                clientList.remove(l)

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

def passtime():
    pass



if __name__ == "__main__":

    HOST, PORT = "localhost", 50007
    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    ip, port = server.server_address

    server_thread = threading.Thread(target=server.serve_forever)


    server_thread.daemon = True
    server_thread.start()
    while server_thread:
       passtime() 


    sys.exit()

我使用 here 的收件箱方法并使用 select.select 我能够检查是否有要读取的输入。

您可以使用 PySock, a python library that make writing multi-client servers extremally easy. You can download it from PyPi, for windows : pip install PySock and for Linux : pip3 install PySock. They have very good boiler plate code on PyPi introduction page. You can check it out here or go to GitHub repo 获取有关版本的更多信息。