美文网首页简友广场想法散文
python socket和多线程实现多人对话聊天室

python socket和多线程实现多人对话聊天室

作者: Cache_wood | 来源:发表于2021-12-31 12:35 被阅读0次

    具体实现

    实现两个python文件,其中server.py包含Manager类,用于充当服务器记录用户的信息,并广播通话内容,实现私聊模式,管理成员的进入和退出。使用多线程服务多个用户。

    client.py文件包含Chatter类,用于与Manager类建立一对一关联,向管理员发送加入和退出请求。其中发送和退出分别使用不同的线程完成。

    最后在用户退出之后log.txt文件可以记录用户的日志并保存到本地磁盘上。

    代码实现

    server.py文件
    import socket,time
    from threading import Thread
    
    class Manager:
        def __init__(self,socket,addr,username):
            self.ip = addr[0]
            self.port = addr[1]
            self.username = username
            self.socket=socket
    
        def sendMsg(self,msg,username):
            try:
                self.socket.send(("%s %s: %s" %(self.getTime(), username, msg)).encode("utf-8"))
                return True
            except:
                return False
    
        def recv(self,mtu=1024):
            try:
                data = self.socket.recv(mtu).decode("utf-8")
                if data == "quit" or not data:
                    return False
                return data
            except:
                return False
            
        def close(self):
            try:
                self.socket.close()
                return True
            except:
                return False
    
        def getId(self):
            return "%s-%s" % (self.ip,self.port)
        def getTime(self):
            return str(time.strftime("%Y-%m-%d %H:%M:%S"))
    
        def new_client(c):
            try:
                print("%s(%s) 尝试连接" %(c.ip,c.port))
                file = open('log.txt','a')
                file.write("%s(%s) 尝试连接\n" %(c.ip,c.port))
    
                data = c.recv()
                if not data:
                    return
                c.username = data
                print("用户%s %s(%s)已连接" %(c.username,c.ip,c.port))
                file.write("用户%s %s(%s)已连接\n" %(c.username,c.ip,c.port))
    
                iports[c.username] = f'{c.ip}-{c.port}'
                c.socket.send("已连接".encode("utf-8"))
                while True:
                    data = c.recv()
                    if not data:
                        break
                    elif data.split(' ')[0] =='@':
                        c.sendMsg(data,c.username)
                        clients[iports[data.split(' ')[1]]].sendMsg(data,c.username)
                    else:
                        print("用户%s %s(%s) 发送了: %s" % (c.username,c.ip, c.port, data))
                        file.write("用户%s %s(%s) 发送了: %s\n" % (c.username,c.ip, c.port, data))
    
                        Manager.broadcast(data,c.username)
    
            except socket.errno as e:
                print("Socket error: %s" % str(e))
            except Exception as e:
                print("Other exception: %s" % str(e))
            finally:
                print("%s(%s) 断开连接" % (c.ip, c.port))
                file.write("%s(%s) 断开连接\n" % (c.ip, c.port))
                #file.close()
    
                c.close()
                clients.pop(c.getId())
    
        def broadcast(msg,username):
            for c in clients.values():
                c.sendMsg(msg,username)
    
    def main(port):
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
        host = "127.0.0.1"
        server.bind((host, port))
    
        # 监听客户端
        server.listen(10)
        print("服务器已开启,正在监听{}".format(server.getsockname()))
    
        while True:
            # 接受客户端连接
            conn, addr = server.accept()
            c = Manager(conn,addr,"")
            clients[c.getId()] = c
            t = Thread(target=Manager.new_client, args=(c,))
            t.start()
    
    if __name__ == "__main__":
        clients = {}
        iports = {}
    
        main(2021)
        print("服务器已关闭")
    
    client.py文件
    import socket
    import time
    from threading import Thread
    
    running = False
    
    class Chatter:
        def send(c):
            time.sleep(0.5)
            while True:
                data = input('')
                c.send(data.encode("utf-8"))
                #file.write(data+'\n')
                #file.close()
    
                if data == "quit":
                    running = False
                    break
    
        def recv(c,t2):
            username = input("输入用户名:")
            #file = open(f'{username}.txt','a')
            #file.write("输入用户名:"+username+'\n')
    
            c.send(username.encode("utf-8"))
            t2.start()
            while running:
                try:
                    data = c.recv(1024).decode("utf-8")
                    if not data:
                        break
                    print(data)
                    #file.write(data+'\n')
                    #file.close()
                except:
                    break
    
    if __name__ == "__main__":
        ip = "127.0.0.1"
        addrs = socket.getaddrinfo(socket.gethostname(), None)
    
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        client.settimeout(0.1)
        client.close()
    
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 导入 socket 模块
        try:
            client.connect((ip, 2021))
            running = True
            t2 = Thread(target=Chatter.send, args=(client,))
            t1 = Thread(target=Chatter.recv, args=(client,t2))
            t1.start()
            t1.join()
            t2.join()
        except:
            pass
        finally:
            print("连接已被关闭")
            #file.close()
    
            client.close()
    

    展示内容

    server.py文件
    client.py文件,用户swx
    client.py文件,用户zly
    client.py文件,用户zjc
    log.txt 日志

    相关文章

      网友评论

        本文标题:python socket和多线程实现多人对话聊天室

        本文链接:https://www.haomeiwen.com/subject/zygrfrtx.html