有时从TcpClient class
读取套接字时,流不会立即解释数据。例如,如果我连接到IRC服务器并且我想解释通道中的文本以识别命令。如果某人键入命令,!time
和!time
是一个有效的函数,它会将当前时间写回服务器。
问题是如果有人以高速率发送相同的命令!time
,则套接字将被淹没。如果其他人试图执行!time
,则在while()循环完成读取泛洪套接字流之前,它不会写回服务器。如果用户不断发送垃圾邮件/泛滥命令,则可能需要几分钟。
static void Connect(String hostname, int port)
{
try
{
socket = new TcpClient(hostname, port);
socket.ReceiveBufferSize = 4096;
Console.WriteLine("Successfully connected to " + hostname);
NetworkStream stream = socket.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
write("USER " + username + " 8 * :" + description, writer);
write("NICK " + username, writer);
write("NS IDENTIFY " + password, writer);//Authenticate account
read(reader);//read the stream
reader.Close();
writer.Close();
stream.Close();
socket.Close();
}
catch
{
Console.WriteLine("Failed to connect to " + hostname);
}
}
下面的read()函数:
static void read(StreamReader reader)
{
try
{
while (true)
{
interpret(reader.ReadLine());
}
}
catch
{
Console.WriteLine("Unable to read from server");
}
}
如果要被洪水淹没,我该怎么办?因此,如果某人确实使用!time
填充了该流,则不会阻止其他用户也看到他们输入!time
的时间。
谢谢。
答案 0 :(得分:1)
Chatbot解决方案
您必须至少处理所有传入文本以分隔消息,并确定用户发送每条消息的内容。然后,您可以按用户将它们拆分为单独的队列。您可以循环处理队列,也可以随机处理队列。或者,您可以实现令牌桶方案,其中每个 n 秒为所有用户提供一定数量的令牌,并且每个命令都使用令牌。不允许用户超过一定数量的令牌( p 秒),他们被允许囤积这些令牌。如果在命令到达时没有该用户的令牌,请将其丢弃或排队,以便下次发出令牌。
服务器端解决方案
其他用户有自己的套接字,不是吗?
一个套接字上的积压不会阻止您阅读其他套接字。你只需要编写应用程序逻辑,这样它就不会被一个人读取,它会循环播放,只有在每个人都有机会之后才从第一个读取更多内容。
通常,您使用select
或WaitAny
之类的函数生成就绪套接字列表。不要总是从列表中的第一个套接字读取,选择最接近你读取的最后一个套接字,或者随机选择一个。