Python网络应用实践|搭建本地聊天室

题目要求

利用socket和多线程,实现支持多人对话的聊天室。具体地,实现Manager和Chatter 两个类,Chatter只需和Manager之间建立一对一联系,而Manager则负责广播或转发所有用户的消息。相关要求如下:

  1. 实现Manager类, 服务器,管理成员进入和离开聊天室,接收成员消息并广播
  2. 实现Chatter类, 用户, 向管理员发送加入和退出请求,发送和接收消息
  3. Manager类使用多线程服务多个用户
  4. Chatter用户发送和接收消息需要依赖不同线程进行
  5. Manager类具备定向转发功能,比如Chatter可以在消息中通过@指定特定用户,这样Manager将仅转发给被指定用户。
  6. Chatter在离开时,自动保存聊天记录到硬盘(包括时间、发信人,信息)。
  7. Manager也应保存所有聊天室记录到硬盘。

任务要求

- Manager 类

  - 成员进入聊天室: 接收消息

  - 成员退出聊天室: 接收消息

  - 定向转发: 以@开头的消息定向转发给对应的用户

    - @ + 用户名

  - 聊天记录保存:

    - 退出聊天室之前保存所有聊天信息


- Chatter 类

  - 定向转发

  - 查看所有成员

  - 退出聊天室时保存本地记录

  - 接收与发送依赖不同进程进行
  • 如何能避免出现input()阻塞了其他用户信息的显示的问题?
    • 可以使用GUI界面,将用户的信息输入过程和其他用户的信息显示分隔开,避免出现上述问题

客户端

登陆GUI

    def welcome(self):
        # 创建登陆界面
        welcome = Tk()
        welcome.title('🎉欢迎使用易聊聊天室  -  Welcome to YChat!')
        welcome.geometry('700x450')

        leftFrame = Frame(welcome)
        rightFrame = Frame(welcome)

        leftFrame.grid(column=0, row=0)
        rightFrame.grid(column=1, row=0)

        photo = PhotoImage(file="bg.png")
        theLabel = Label(leftFrame,
                         image=photo,  # 加入图片
                         compound=CENTER,  # 关键:设置为背景图片
                         fg="white")  # 前景色
        theLabel.pack(pady=10)

        nameLabel = Label(rightFrame,
                          text='请输入你的昵称:',
                          font=('PingFang HK', 14),
                          height=1,
                          fg='black')
        nameLabel.grid(row=0, sticky=W)

        usernameEntry = Entry(rightFrame,
                              font=('PingFang HK', 20),
                              width=17, )
        usernameEntry.grid(row=1, sticky=W, pady=10)

        ipLabel = Label(rightFrame,
                        text='请输入聊天室 IP:',
                        font=('PingFang HK', 14),
                        height=1,
                        fg='black')
        ipLabel.grid(row=2, sticky=W)

        ipEntry = Entry(rightFrame,
                        font=('PingFang HK', 20),
                        width=17, )
        ipEntry.grid(row=3, sticky=W, pady=10)

        portLabel = Label(rightFrame,
                          text='请输入端口号:',
                          font=('PingFang HK', 14),
                          height=1,
                          fg='black')
        portLabel.grid(row=4, sticky=W)

        portEntry = Entry(rightFrame,
                          font=('PingFang HK', 20),
                          width=17, )
        portEntry.grid(row=5, sticky=W, pady=10)

        def login():
            global user, IP, PORT
            user = usernameEntry.get()
            IP = ipEntry.get()
            PORT = portEntry.get()

            if not user:
                tkinter.messagebox.showwarning('⚠️输入错误!', message='用户名为空!')
            else:
                if not IP:
                    tkinter.messagebox.showwarning('⚠️输入错误!', message='IP 地址为空!')
                else:
                    if not PORT:
                        tkinter.messagebox.showwarning('⚠️输入错误!', message='端口号为空!')
                    else:
                        welcome.destroy()

        button = Button(rightFrame,
                        text='进入聊天室',
                        font=('PingFang HK', 14),
                        height=2,
                        width=12,
                        command=login)
        button.grid(row=6, pady=15)

        button = Button(rightFrame,
                        text='退出',
                        font=('PingFang HK', 14),
                        height=2,
                        width=12,
                        command=exit)
        button.grid(row=7)

        welcome.mainloop()

聊天界面

 # 聊天室 GUI
        root = Tk()
        root.geometry('800x600')
        root.title('💬聊天室 - YChat - 用户: {}'.format(self._user))
        root.resizable(0, 0)

        # 消息栏
        listbox = ScrolledText(root,
                               font=('PingFang HK', 16))
        listbox.place(x=20,
                      y=20,
                      width=580,
                      height=380)
        listbox.tag_config('tag1',
                           foreground='red',
                           backgroun="yellow")
        listbox.insert(tkinter.END, '欢迎进入群聊,大家开始聊天吧!\n', 'tag1')

        # 输入框
        INPUT = StringVar()
        INPUT.set('')
        entryIuput = Entry(root,
                           width=120,
                           textvariable=INPUT,
                           font=('PingFang HK', 16))
        entryIuput.place(x=20,
                         y=420,
                         width=580,
                         height=160)

        # 在线用户列表
        listbox1 = Listbox(root,
                           font=('PingFang HK', 14))
        listbox1.place(x=620,
                       y=20,
                       width=160,
                       height=380)

        sendButton = tkinter.Button(root,
                                    text="发  送",
                                    anchor='n',
                                    command=sendmsg,
                                    font=('PingFang HK', 18), bg='white', pady=12)
        sendButton.place(x=620,
                         y=470,
                         width=160,
                         height=60)

        # 首先启动接收进程
        q = Thread(target=receive)
        q.start()

        root.mainloop()

        save_log(self._filepath, CHARTLOG)
        self._client.close()

发送消息

  • 我们定义信息格式如下:
<user>小米</user>
<time>2021-12-29 20:33:14.066927</time>
<msg>大家好!</msg>
        def sendmsg():
            msg = entryIuput.get()

            now_time = datetime.datetime.now()
            msg_cont = """\n<user>{}</user>\n<time>{}</time>\n<msg>{}</msg>\n""". \
                format(self._user, str(now_time), msg)
            self._client.send(msg_cont.encode('utf-8'))

            INPUT.set('')

接收消息

  • 接收消息并显示消息,这里我们将消息分为三种类型
    • 警报消息
    • 普通消息
    • 本人消息
    分别用不同的颜色表示
        def receive():

            global fg, bg
            while True:
                msg = self._client.recv(BUFFERS).decode('utf-8')
                print(msg)
                print('\n')

                try:
                    uses = json.loads(msg)
                    listbox1.delete(0, tkinter.END)
                    listbox1.insert(tkinter.END, "当前在线用户")
                    listbox1.insert(tkinter.END, "------Group chat-------")
                    for x in range(len(uses)):
                        listbox1.insert(tkinter.END, uses[x])
                    users.append('------Group chat-------')

                except:
                    user = re.findall(r'<user>(.+)</user>', msg)
                    message = re.findall(r'<msg>(.+)</msg>', msg)
                    time = re.findall(r'<svtime>(.+)</svtime>', msg)

                    save_log(self._filepath, msg)

                    user = user[0]
                    message = message[0]
                    time = time[0]

                    listbox.tag_config('tag2',
                                       foreground='white',
                                       backgroun='blue')
                    listbox.tag_config('tag3',
                                       foreground='red',
                                       backgroun='yellow')
                    listbox.tag_config('tag4',
                                       foreground='black',
                                       backgroun='white')

                    outputmsg = '{}\n{}: {}\n'.format(time, user, message)

                    if user == self._user:
                        listbox.insert(tkinter.END, outputmsg, 'tag2')

                    elif user == '系统消息':
                        listbox.insert(tkinter.END, outputmsg, 'tag3')

                    else:
                        listbox.insert(tkinter.END, outputmsg, 'tag4')

                    listbox.see(tkinter.END)

        self._client.connect((self._ip, self._port))
        user_info = '<user>{}</user>'.format(self._user)
        self._client.send(user_info.encode('utf-8'))

文件保存

def save_log(path, content):
    with open(path, 'a', encoding='utf-8') as f:
        f.writelines(content)
        f.close()

在运行过程中,每接收到一条消息,便写入一条消息:

使用的库和全局变量

import os
import json
import datetime
from socket import *
from tkinter import *
import tkinter.messagebox
from threading import Thread
from tkinter.scrolledtext import ScrolledText

PATH = '/Users/indecreasy/Desktop/212_MPD/P13/'
LOCALHOST = '127.0.0.1'  # LOCALHOST IP 号,用于在本地模拟服务端和客户端
PORT = 4399
users = []
BUFFERS = 1024
MAXC = 64
CHARTLOG = []

服务器端

  • 采用队列来管理信息的发送顺序;
  • 服务器完成信息的接收、处理和转发;
    • 重点解决@转发的问题
  • 接收和转发采用两个线程来完成

主要部分

  • 启动了播报线程,之后每接收到一个新链接,便启动一个监听线程
    def __init__(self, ip, port):
        self._ip = ip
        self._port = port

        self._filepath = '{}/{}.txt'.format(PATH, 'server')
        file = open(self._filepath, 'w')
        file.close()

        self.launch()

    def launch(self):
        server = socket(AF_INET, SOCK_STREAM)
        server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)  # 端口释放后马上可以被重新使用
        server.bind((self._ip, self._port))
        server.listen(MAXC)
        print('Server is started...')
        q = threading.Thread(target=self.senddata)
        q.start()

        while True:
            # 接受连接后,启动一个线程处理该连接,主线程继续处理其他连接
            conn, addr = server.accept()

            t = Thread(target=self.speak, args=(conn, addr))
            t.start()

        server.close()

监听线程

  • 此线程同时完成在线用户的管理
    def speak(self, conn, addr):
        user_info = conn.recv(BUFFERS).decode('utf-8')  # 接收自动播报的用户名

        # 提取用户名
        # 正则表达式匹配, 提取用户名
        nameMatch = re.match(r'^<user>', user_info)
        if nameMatch:
            pattern = re.compile('<user>(.+)</user>')
            username = pattern.findall(user_info)
            username = username[0]

        user_list.append((username, conn, addr))
        online_users = onlines()
        self.load(online_users, addr, flag='users')

        boarding = '{} ({} - {}) 进入了聊天室'.format(username, addr[0], addr[1])
        print(boarding)

        try:
            while True:
                msg = conn.recv(BUFFERS).decode('utf-8')
                server_time = datetime.datetime.now()
                msg = msg + '<svtime>{}</svtime>\n'.format(str(server_time))

                self.load(msg, addr, flag='msg')

            conn.close()

        except:
            # 用户断开连接
            j = 0
            for user in user_list:
                if user[0] == username:
                    user_list.pop(j)  # 服务器段删除退出的用户
                    break
                j = j + 1

            online_users = onlines()
            self.load(online_users, addr, flag='users')
            conn.close()
  • 统计在线人数:
def onlines():  # 统计当前在线人员
    online = []
    for i in range(len(user_list)):
        online.append(user_list[i][0])
    return online

播报线程

  • 重点是在此处完成个别用户的转发
  • 同时设置了警报信息
    • 针对被私聊用户的提示信息
    • @用户名 不存在后的警告信息
    def senddata(self):
        # 将信息和用户列表转发给各个客户端
        global raw_conn
        while True:
            if not messages.empty():
                message = messages.get()
                content, addr, flag = message

                if flag == 'msg':
                    save_log(self._filepath, content)

                    # 判断原语句中是否有@

                    atMatch = re.search(r'<msg>(@.+) ', content)

                    if atMatch:
                        pattern = re.findall(r'@(.+) ', content)
                        user = pattern[0]

                        raw_user = re.findall(r'<user>(.+)</user>', content)
                        raw_user = raw_user[0]

                        fflag = 0

                        for i in range(len(user_list)):
                            if user_list[i][0] == user:
                                warning = '<user>系统消息</user>\n<time>系统消息</time>\n<msg' \
                                          '>有人对您发送了私聊信息!</msg>\n<svtime>系统消息</svtime> '
                                user_list[i][1].send(warning.encode('utf-8'))
                                time.sleep(1)
                                user_list[i][1].send(content.encode('utf-8'))
                                fflag = 1

                            if user_list[i][0] == raw_user:
                                raw_conn = user_list[i][1]

                        if fflag == 1:
                            for i in range(len(user_list)):
                                if user_list[i][0] == raw_user:
                                    raw_conn = user_list[i][1]
                                    raw_conn.send(content.encode('utf-8'))

                        if fflag == 0:
                            for i in range(len(user_list)):
                                if user_list[i][0] == raw_user:
                                    warning = '<user>系统消息</user>\n<time>系统消息</time>\n<msg>您 @ ' \
                                              '的用户不存在或当前不在线!消息发送失败!</msg>\n<svtime>系统消息</svtime> '
                                    raw_conn.send(content.encode('utf-8'))
                                    time.sleep(1)
                                    raw_conn.send(warning.encode('utf-8'))

                    else:
                        for i in range(len(user_list)):
                            user_list[i][1].send(content.encode('utf-8'))

                if flag == 'users':
                    data = json.dumps(content)

                    for i in range(len(user_list)):
                        try:
                            user_list[i][1].send(data.encode())

                        except:
                            pass

使用的库和全局变量

import os
import re
import time
import json
import queue
import datetime
import os.path
import threading
from socket import *
from threading import Thread

PATH = '/Users/indecreasy/Desktop/212_MPD/P13/'
LOCALHOST = '127.0.0.1'  # LOCALHOST IP 号,用于在本地模拟服务端和客户端
PORT = 4399

BUFFERS = 1024
MAXC = 64
user_list = []
messages = queue.Queue()
lock = threading.Lock()

聊天信息的保存

疑难解决

  • 过程中遇到了 地址被占用的情况,情况如:
socket.error: [Errno 48] Address already in use

//如上报错,错误号48;端口已被占用。
  • 参考:
sudo lsof -i:4399

sudo kill *pid*
  • 将占用端口的python进程结束,解决了该问题。

运行截图

警报信息示例:

References

https://www.liujiangblog.com/course/python/76

https://www.cnblogs.com/Beyond-Ricky/p/8079602.html

https://blog.csdn.net/calling_wisdom/article/details/42524745

https://zhuanlan.zhihu.com/p/269100912

https://blog.csdn.net/weixin_46112690/article/details/121704851

https://zhuanlan.zhihu.com/p/140496484

https://blog.csdn.net/t8116189520/article/details/80137916

源代码

客户端

import os
import json
import datetime
from socket import *
from tkinter import *
import tkinter.messagebox
from threading import Thread
from tkinter.scrolledtext import ScrolledText

PATH = '/Users/indecreasy/Desktop/212_MPD/P13/'
LOCALHOST = '127.0.0.1'  # LOCALHOST IP 号,用于在本地模拟服务端和客户端
PORT = 4399
users = []
BUFFERS = 1024
MAXC = 64
CHARTLOG = []


def save_log(path, content):
    with open(path, 'a', encoding='utf-8') as f:
        f.writelines(content)
        f.close()


class Chatter:

    def __init__(self):
        self.welcome()
        # user = 'Issac'
        # IP = '127.0.0.1'
        # PORT = 4399
        self._user = user
        self._ip = IP
        self._port = int(PORT)
        self._filepath = '{}/{}.txt'.format(PATH, self._user)

        file = open(self._filepath, 'w')
        file.close()

        self._client = socket(AF_INET, SOCK_STREAM)
        self.get_socket()

    def welcome(self):
        # 创建登陆界面
        welcome = Tk()
        welcome.title('🎉欢迎使用易聊聊天室  -  Welcome to YChat!')
        welcome.geometry('700x450')

        leftFrame = Frame(welcome)
        rightFrame = Frame(welcome)

        leftFrame.grid(column=0, row=0)
        rightFrame.grid(column=1, row=0)

        photo = PhotoImage(file="bg.png")
        theLabel = Label(leftFrame,
                         image=photo,  # 加入图片
                         compound=CENTER,  # 关键:设置为背景图片
                         fg="white")  # 前景色
        theLabel.pack(pady=10)

        nameLabel = Label(rightFrame,
                          text='请输入你的昵称:',
                          font=('PingFang HK', 14),
                          height=1,
                          fg='black')
        nameLabel.grid(row=0, sticky=W)

        usernameEntry = Entry(rightFrame,
                              font=('PingFang HK', 20),
                              width=17, )
        usernameEntry.grid(row=1, sticky=W, pady=10)

        ipLabel = Label(rightFrame,
                        text='请输入聊天室 IP:',
                        font=('PingFang HK', 14),
                        height=1,
                        fg='black')
        ipLabel.grid(row=2, sticky=W)

        ipEntry = Entry(rightFrame,
                        font=('PingFang HK', 20),
                        width=17, )
        ipEntry.grid(row=3, sticky=W, pady=10)

        portLabel = Label(rightFrame,
                          text='请输入端口号:',
                          font=('PingFang HK', 14),
                          height=1,
                          fg='black')
        portLabel.grid(row=4, sticky=W)

        portEntry = Entry(rightFrame,
                          font=('PingFang HK', 20),
                          width=17, )
        portEntry.grid(row=5, sticky=W, pady=10)

        def login():
            global user, IP, PORT
            user = usernameEntry.get()
            IP = ipEntry.get()
            PORT = portEntry.get()

            if not user:
                tkinter.messagebox.showwarning('⚠️输入错误!', message='用户名为空!')
            else:
                if not IP:
                    tkinter.messagebox.showwarning('⚠️输入错误!', message='IP 地址为空!')
                else:
                    if not PORT:
                        tkinter.messagebox.showwarning('⚠️输入错误!', message='端口号为空!')
                    else:
                        welcome.destroy()

        button = Button(rightFrame,
                        text='进入聊天室',
                        font=('PingFang HK', 14),
                        height=2,
                        width=12,
                        command=login)
        button.grid(row=6, pady=15)

        button = Button(rightFrame,
                        text='退出',
                        font=('PingFang HK', 14),
                        height=2,
                        width=12,
                        command=exit)
        button.grid(row=7)

        welcome.mainloop()

    def get_socket(self):

        def receive():

            global fg, bg
            while True:
                msg = self._client.recv(BUFFERS).decode('utf-8')
                print(msg)
                print('\n')

                try:
                    uses = json.loads(msg)
                    listbox1.delete(0, tkinter.END)
                    listbox1.insert(tkinter.END, "当前在线用户")
                    listbox1.insert(tkinter.END, "------Group chat-------")
                    for x in range(len(uses)):
                        listbox1.insert(tkinter.END, uses[x])
                    users.append('------Group chat-------')

                except:
                    user = re.findall(r'<user>(.+)</user>', msg)
                    message = re.findall(r'<msg>(.+)</msg>', msg)
                    time = re.findall(r'<svtime>(.+)</svtime>', msg)

                    save_log(self._filepath, msg)

                    user = user[0]
                    message = message[0]
                    time = time[0]

                    listbox.tag_config('tag2',
                                       foreground='white',
                                       backgroun='blue')
                    listbox.tag_config('tag3',
                                       foreground='red',
                                       backgroun='yellow')
                    listbox.tag_config('tag4',
                                       foreground='black',
                                       backgroun='white')

                    outputmsg = '{}\n{}: {}\n'.format(time, user, message)

                    if user == self._user:
                        listbox.insert(tkinter.END, outputmsg, 'tag2')

                    elif user == '系统消息':
                        listbox.insert(tkinter.END, outputmsg, 'tag3')

                    else:
                        listbox.insert(tkinter.END, outputmsg, 'tag4')

                    listbox.see(tkinter.END)

        self._client.connect((self._ip, self._port))
        user_info = '<user>{}</user>'.format(self._user)
        self._client.send(user_info.encode('utf-8'))

        def sendmsg():
            msg = entryIuput.get()

            now_time = datetime.datetime.now()
            msg_cont = """\n<user>{}</user>\n<time>{}</time>\n<msg>{}</msg>\n""". \
                format(self._user, str(now_time), msg)
            self._client.send(msg_cont.encode('utf-8'))

            INPUT.set('')


        # 聊天室 GUI
        root = Tk()
        root.geometry('800x600')
        root.title('💬聊天室 - YChat - 用户: {}'.format(self._user))
        root.resizable(0, 0)

        # 消息栏
        listbox = ScrolledText(root,
                               font=('PingFang HK', 16))
        listbox.place(x=20,
                      y=20,
                      width=580,
                      height=380)
        listbox.tag_config('tag1',
                           foreground='red',
                           backgroun="yellow")
        listbox.insert(tkinter.END, '欢迎进入群聊,大家开始聊天吧!\n', 'tag1')

        # 输入框
        INPUT = StringVar()
        INPUT.set('')
        entryIuput = Entry(root,
                           width=120,
                           textvariable=INPUT,
                           font=('PingFang HK', 16))
        entryIuput.place(x=20,
                         y=420,
                         width=580,
                         height=160)

        # 在线用户列表
        listbox1 = Listbox(root,
                           font=('PingFang HK', 14))
        listbox1.place(x=620,
                       y=20,
                       width=160,
                       height=380)

        sendButton = tkinter.Button(root,
                                    text="发  送",
                                    anchor='n',
                                    command=sendmsg,
                                    font=('PingFang HK', 18), bg='white', pady=12)
        sendButton.place(x=620,
                         y=470,
                         width=160,
                         height=60)

        # 首先启动接收进程
        q = Thread(target=receive)
        q.start()

        root.mainloop()

        save_log(self._filepath, CHARTLOG)
        self._client.close()


if __name__ == '__main__':
    a = Chatter()

服务器

import os
import re
import time
import json
import queue
import datetime
import os.path
import threading
from socket import *
from threading import Thread

PATH = '/Users/indecreasy/Desktop/212_MPD/P13/'
LOCALHOST = '127.0.0.1'  # LOCALHOST IP 号,用于在本地模拟服务端和客户端
PORT = 4399

BUFFERS = 1024
MAXC = 64
user_list = []
messages = queue.Queue()
lock = threading.Lock()


def save_log(path, content):
    with open(path, 'a', encoding='utf-8') as f:
        f.writelines(content)
        f.close()


def onlines():  # 统计当前在线人员
    online = []
    for i in range(len(user_list)):
        online.append(user_list[i][0])
    return online


class Manager:
    """
    服务器的 Manager 类,用于完成要求的需求
    - __init__()
    - speak() 完成接受于广播
    - launch() 启动后的初始化内容
    """

    def __init__(self, ip, port):
        self._ip = ip
        self._port = port

        self._filepath = '{}/{}.txt'.format(PATH, 'server')
        file = open(self._filepath, 'w')
        file.close()

        self.launch()

    def launch(self):
        server = socket(AF_INET, SOCK_STREAM)
        server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)  # 端口释放后马上可以被重新使用
        server.bind((self._ip, self._port))
        server.listen(MAXC)
        print('Server is started...')
        q = threading.Thread(target=self.senddata)
        q.start()

        while True:
            # 接受连接后,启动一个线程处理该连接,主线程继续处理其他连接
            conn, addr = server.accept()

            t = Thread(target=self.speak, args=(conn, addr))
            t.start()

        server.close()

    def speak(self, conn, addr):
        user_info = conn.recv(BUFFERS).decode('utf-8')  # 接收自动播报的用户名

        # 提取用户名
        # 正则表达式匹配, 提取用户名
        nameMatch = re.match(r'^<user>', user_info)
        if nameMatch:
            pattern = re.compile('<user>(.+)</user>')
            username = pattern.findall(user_info)
            username = username[0]

        user_list.append((username, conn, addr))
        online_users = onlines()
        self.load(online_users, addr, flag='users')

        boarding = '{} ({} - {}) 进入了聊天室'.format(username, addr[0], addr[1])
        print(boarding)

        try:
            while True:
                msg = conn.recv(BUFFERS).decode('utf-8')
                server_time = datetime.datetime.now()
                msg = msg + '<svtime>{}</svtime>\n'.format(str(server_time))

                self.load(msg, addr, flag='msg')

            conn.close()

        except:
            # 用户断开连接
            j = 0
            for user in user_list:
                if user[0] == username:
                    user_list.pop(j)  # 服务器段删除退出的用户
                    break
                j = j + 1

            online_users = onlines()
            self.load(online_users, addr, flag='users')
            conn.close()

    def load(self, content, addr, flag):
        lock.acquire()
        try:
            messages.put((content, addr, flag))
        finally:
            lock.release()

    def senddata(self):
        # 将信息和用户列表转发给各个客户端
        global raw_conn
        while True:
            if not messages.empty():
                message = messages.get()
                content, addr, flag = message

                if flag == 'msg':
                    save_log(self._filepath, content)

                    # 判断原语句中是否有@

                    atMatch = re.search(r'<msg>(@.+) ', content)

                    if atMatch:
                        pattern = re.findall(r'@(.+) ', content)
                        user = pattern[0]

                        raw_user = re.findall(r'<user>(.+)</user>', content)
                        raw_user = raw_user[0]

                        fflag = 0

                        for i in range(len(user_list)):
                            if user_list[i][0] == user:
                                warning = '<user>系统消息</user>\n<time>系统消息</time>\n<msg' \
                                          '>有人对您发送了私聊信息!</msg>\n<svtime>系统消息</svtime> '
                                user_list[i][1].send(warning.encode('utf-8'))
                                time.sleep(1)
                                user_list[i][1].send(content.encode('utf-8'))
                                fflag = 1

                            if user_list[i][0] == raw_user:
                                raw_conn = user_list[i][1]

                        if fflag == 1:
                            for i in range(len(user_list)):
                                if user_list[i][0] == raw_user:
                                    raw_conn = user_list[i][1]
                                    raw_conn.send(content.encode('utf-8'))

                        if fflag == 0:
                            for i in range(len(user_list)):
                                if user_list[i][0] == raw_user:
                                    warning = '<user>系统消息</user>\n<time>系统消息</time>\n<msg>您 @ ' \
                                              '的用户不存在或当前不在线!消息发送失败!</msg>\n<svtime>系统消息</svtime> '
                                    raw_conn.send(content.encode('utf-8'))
                                    time.sleep(1)
                                    raw_conn.send(warning.encode('utf-8'))

                    else:
                        for i in range(len(user_list)):
                            user_list[i][1].send(content.encode('utf-8'))

                if flag == 'users':
                    data = json.dumps(content)

                    for i in range(len(user_list)):
                        try:
                            user_list[i][1].send(data.encode())

                        except:
                            pass


if __name__ == '__main__':
    manager = Manager(LOCALHOST, PORT)

Related Posts