在java(IRC)中避免速率限制(限制)

时间:2015-01-21 09:41:51

标签: java time irc rate

所以我一直在写一个基于java的irc-bot,这很简单。建立与服务器的套接字连接,将缓冲的读取器/写入器连接到套接字,然后使用这些缓冲区进行读/写。

除了当我打印出一个json对象并因为过多的洪水而被踢出网络时,我没有遇到任何问题。我不确定网络的消息速率限制,但我通过相同的简单功能传递所有消息。

我希望为它添加某种x字节/时间帧限制。有人建议我调查NIO,但这似乎对这个问题有点过度设计。

这是我当前的写入irc通道方法的样子:

public static void writeMsg(BufferedWriter writer, String Channel, String Message){
    try {
        System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
        writer.write("PRIVMSG " + Channel + Message);
        writer.flush();
    }catch(IOException ioe){ioe.printStackTrace(); }
}

可能传入/传出该函数的示例:

输入:

writer(我的BufferedWriter对象),“#Testing1234:”,“!wiki China”;

输出:PRIVMSG #BeginnersProgramming:http://en.wikipedia.org/wiki/China

由于

2 个答案:

答案 0 :(得分:1)

  

我希望为它添加某种x字节/时间帧限制

最简单的方法是

final int rateLimit = 50; // Bytes per second

final float msPerByte = 1000.0f / rateLimit;

writer.write(message);

int numBytes = message.length();

Thread.sleep((int)(msPerByte * numBytes + 1));

但是,根据消息的长度,一条消息的单个突发可能已经触发了服务器的速率限制。在这种情况下,您必须将消息拆分为较小的部分,然后在两者之间以适当的延迟发送。

如果仅在每个时间帧的消息上强制实施速率限制,那么您需要做的只是sleep()每条消息后的一个固定时间。

我相信虽然有更复杂的算法在起作用,但可能包含更多基于时间的参数来决定。

答案 1 :(得分:0)

我会在你方法的开头随机睡一觉。这样,您就可以模拟人类输入。

非线程安全版

private static SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN"); 

public static void writeMsg(BufferedWriter writer, String Channel, String Message){
    try {
        // Sleep randomly between 2 (inclusive) and 5 (exclusive) seconds.
        int duration = 2000 + sr.nextInt(3000);
        System.out.println("Pausing execution for " + duration + " ms..."); 
        TimeUnit.MILLISECONDS.sleep(duration);

        System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
        writer.write("PRIVMSG " + Channel + Message);
        writer.flush();
    } catch(IOException ioe){
       ioe.printStackTrace();
    } catch (InterruptedException e) {
       e.printStackTrace();
    }
}

线程安全版

如果您的方法将由多个线程调用,请考虑使用锁定此代码。锁在发送消息时会增加一些随机性。

private static final Lock writeLock = new ReentrantLock();
private static SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN"); 

public static void writeMsg(BufferedWriter writer, String Channel, String Message){
    writeLock.lock();
    try {
        // Sleep randomly between 2 (inclusive) and 5 (exclusive) seconds.
        int duration = 2000 + sr.nextInt(3000);
        System.out.println("Pausing execution for " + duration + " ms..."); 
        TimeUnit.MILLISECONDS.sleep(duration);

        System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
        writer.write("PRIVMSG " + Channel + Message);
        writer.flush();
    } catch(IOException ioe){
       ioe.printStackTrace();
    } catch (InterruptedException e) {
       e.printStackTrace();
    } finally {
       writeLock.unlock();
    }
}