有没有办法限制客户端在 Python 聊天室应用程序中发送的消息数/秒?

Posted

技术标签:

【中文标题】有没有办法限制客户端在 Python 聊天室应用程序中发送的消息数/秒?【英文标题】:Is there a way to limit the number of messages/second the client is sending in a Python chatroom application? 【发布时间】:2021-01-04 19:44:15 【问题描述】:

我正在使用功能正常的客户端和服务器端脚本为学校制作 python 聊天室应用程序。我现在正在向聊天室添加多种功能以使其更易于使用,其中之一希望是垃圾邮件保护。有没有一种方法可以记录客户端发送的特定时间测量的消息数量,如果超过最大值,它们会在一定时间内静音?

clientside.py:

from socket import AF_INET, socket, SOCK_STREAM
from threading import Thread
import tkinter as tkinter
#import tkinter.ttk as ttk
#from ttkthemes import ThemedStyle
from tkinter import END
from datetime import *
import time as tme
def receive():
    while True:
        try:
            msg = client_socket.recv(BUFSIZ).decode("utf8")
            now = datetime.now()
            current_time = now.strftime("%H:%M:%S")
            msg_list.insert(tkinter.END, '[' + current_time + '] ' + msg)
            msg_list.yview(END)
            msg_list.yview()
        except OSError:
            break
def send(event=None):
    msg = my_msg.get()
    if msg.isspace() != True:
        my_msg.set("")
        client_socket.send(bytes(msg, "utf8"))
        msg_list.yview(END)
        msg_list.yview()
    elif msg.isspace() == True:
        my_msg.set("")
    if msg == "quit":
        client_socket.close()
        top.quit()
def on_closing(event=None):
    top.destroy()
    my_msg.set("quit")
    send()
    top.quit()
top = tkinter.Tk()
top.resizable(width=False, height=False)
#top.iconbitmap('C:/Users/Ethen Dixon/Downloads/filled_chat_aH2_icon.ico')
top.title("Chat Room 90")
#style = ThemedStyle(top)
#style.set_theme("equilux")
messages_frame = tkinter.Frame(top)
my_msg = tkinter.StringVar()
my_msg.set("[type here]")
scrollbar = tkinter.Scrollbar(messages_frame)
msg_list = tkinter.Listbox(messages_frame, height=30, width=100, yscrollcommand=scrollbar.set)
scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
msg_list.pack()
messages_frame.pack()
entry_field = tkinter.Entry(top, textvariable=my_msg, width=100)
entry_field.bind("<Return>", send)
entry_field.pack()
send_button = tkinter.Button(top, text="Send", command=send)
send_button.pack()
top.protocol("WM_DELETE_WINDOW", on_closing)

HOST = input('Enter host: ')
PORT = input('Enter port: ')
if not PORT:
    PORT = 33000
else:
    PORT = int(PORT)
BUFSIZ = 1024
ADDR = (HOST, PORT)
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(ADDR)
receive_thread = Thread(target=receive)
receive_thread.start()
tkinter.mainloop()

服务器端.py:

from socket import AF_INET, socket, SOCK_STREAM
from threading import Thread
def accept_incoming_connections():
    """Sets up handling for incoming clients."""
    while True:
        client, client_address = SERVER.accept()
        print("%s:%s has connected." % client_address)
        client.send(bytes("Welcome to Chat Room 90! Please type in your username and press enter.", "utf8"))
        addresses[client] = client_address
        Thread(target=handle_client, args=(client,)).start()
def handle_client(client):
    """Handles a single client connection."""
    name = client.recv(BUFSIZ).decode("utf8")
    welcome = 'Welcome %s!' % name
    client.send(bytes(welcome, "utf8"))
    msg = "%s has joined the chat!" % name
    broadcast(bytes(msg, "utf8"))
    clients[client] = name
    while True:
        msg = client.recv(BUFSIZ)
        if msg != bytes("quit", "utf8"):
            broadcast(msg, name+": ")
        else:
            client.send(bytes("quit", "utf8"))
            client.close()
            del clients[client]
            broadcast(bytes("%s has left the chat." % name, "utf8"))
            break
def broadcast(msg, prefix=""):
    """Broadcasts a message to all the clients."""
    for sock in clients:
        sock.send(bytes(prefix, "utf8")+msg)
clients = 
addresses = 
HOST = ''
PORT = 33000
BUFSIZ = 1024
ADDR = (HOST, PORT)
SERVER = socket(AF_INET, SOCK_STREAM)
SERVER.bind(ADDR)
if __name__ == "__main__":
    SERVER.listen(5)
    print("Waiting for connection...")
    ACCEPT_THREAD = Thread(target=accept_incoming_connections)
    ACCEPT_THREAD.start()
    ACCEPT_THREAD.join()
    SERVER.close()

【问题讨论】:

是的,有很多方法可以做到这一点。你认为你可以尝试什么? 与 time.sleep(x) 有关,但在尝试后它只是减慢了应用程序和发送的消息 你可以只发消息吗? 推测在客户端实施的任何限制都可以被用户删除以打破限制;更好的方法是在服务器端安装速率限制逻辑,例如将传入消息添加到 FIFO 队列的尾部,并且仅以每秒 1 个或其他的最大速率从队列头部弹出它们(转发到其他客户端)。 (不要忘记将 FIFO 队列的大小限制在一个合理的最大值,这样不怀好意的用户就无法使用它来填满服务器的 RAM) 【参考方案1】:

一种方法是使用widget.unbind(sequence, funcid = None) 方法。 顾名思义,这会删除已确定事件的 w 上的绑定。

然后您可以使用 tkinter 内置方法 root.after() 调用您创建的函数以将按钮重新绑定到该函数。

但要使其工作,您需要使用 .bind() 方法绑定 send_button。


def rebind():
     send_button.bind("<Button-1>", send)
     
send_button.bind("<Button-1>", send)
send_button.unbind("<Button-1>", funcid=None) 
top.after(time in miliseconds, rebind)

【讨论】:

创建按钮时不要忘记删除命令

以上是关于有没有办法限制客户端在 Python 聊天室应用程序中发送的消息数/秒?的主要内容,如果未能解决你的问题,请参考以下文章

Python socket实现服务器客户端聊天通讯

Openfire 限制聊天客户端

有没有办法在带有可选 AR 过滤器的颤振应用程序中实现视频聊天?

Python上的聊天客户端/服务器问题

限制对 java、c++、python 程序的权限 [关闭]

GUI 应用:socket 网络聊天室