简友广场想法散文

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

2021-12-31  本文已影响0人  Cache_wood

具体实现

实现两个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 日志
上一篇 下一篇

猜你喜欢

热点阅读