有没有办法限制客户端在 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 聊天室应用程序中发送的消息数/秒?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在带有可选 AR 过滤器的颤振应用程序中实现视频聊天?