一个常见的错误是假设IDLE命令将不间断地发布更新.然而,定义IDLE扩展的

RFC 2177表示:

The server MAY consider a client inactive if it has an IDLE command

running, and if such a server has an inactivity timeout it MAY log

the client off implicitly at the end of its timeout period. Because

of that, clients using IDLE are advised to terminate the IDLE and

re-issue it at least every 29 minutes to avoid being logged off.

This still allows a client to receive immediate mailbox updates even

though it need only “poll” at half hour intervals.

特别是GMail,如你所说,大约10分钟,有一个低得多的超时时间.

我们只需要每9分钟左右重新发行一次IDLE命令,让它工作. javax.mail API无法为IDLE命令设置超时,因此您将需要一个第二个线程来移动此操作.

第一种方法是让第二个线程中断第一个线程,处理异常并忽略它.然而,这将允许没有干净的方式来关闭线程,所以我不会推荐它.一个更清洁的方法是让第二个线程向服务器发出一个NOOP命令.这完全没有,但是足够让IDLE中止并重新发行.

我在这里提供一些代码来做到这一点:

public void startListening(IMAPFolder imapFolder) {

// We need to create a new thread to keep alive the connection

Thread t = new Thread(

new KeepAliveRunnable(imapFolder), "IdleConnectionKeepAlive"

);

t.start();

while (!Thread.interrupted()) {

LOGGER.debug("Starting IDLE");

try {

imapFolder.idle();

} catch (MessagingException e) {

LOGGER.warn("Messaging exception during IDLE", e);

throw new RuntimeException(e);

}

}

// Shutdown keep alive thread

if (t.isAlive()) {

t.interrupt();

}

}

/**

* Runnable used to keep alive the connection to the IMAP server

*

* @author Juan Martín Sotuyo Dodero

*/

private static class KeepAliveRunnable implements Runnable {

private static final long KEEP_ALIVE_FREQ = 300000; // 5 minutes

private IMAPFolder folder;

public KeepAliveRunnable(IMAPFolder folder) {

this.folder = folder;

}

@Override

public void run() {

while (!Thread.interrupted()) {

try {

Thread.sleep(KEEP_ALIVE_FREQ);

// Perform a NOOP just to keep alive the connection

LOGGER.debug("Performing a NOOP to keep alvie the connection");

folder.doCommand(new IMAPFolder.ProtocolCommand() {

public Object doCommand(IMAPProtocol p)

throws ProtocolException {

p.simpleCommand("NOOP", null);

return null;

}

});

} catch (InterruptedException e) {

// Ignore, just aborting the thread...

} catch (MessagingException e) {

// Shouldn't really happen...

LOGGER.warn("Unexpected exception while keeping alive the IDLE connection", e);

}

}

}

}

Logo

一站式 AI 云服务平台

更多推荐