所以我一直在写一个基于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
由于
答案 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();
}
}