我决定让我的客户定期“ping”服务器,以便我知道客户端仍然存在。我正在使用嵌入在Java应用程序中的Jetty服务器,我有一个HttpServlet来处理客户端请求。
在服务器端,我怎么知道客户端什么时候没有“ping”(发送请求)?
答案 0 :(得分:2)
通过其sessionID识别客户端,并跟踪上次ping。定期扫描所有最后一次ping,找到那些没有在N分钟内进行ping操作的人。
答案 1 :(得分:2)
扩展srini.venigalla的答案,你可以使用这样的东西作为起点。
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.*;
public class PingServlet extends HttpServlet {
private static final long EXPIRATION_MILLIS = TimeUnit.SECONDS.toMillis(30);
private final ConcurrentMap<String, Long> sessionIdToLastPingTime = new ConcurrentHashMap<String, Long>();
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
public void init() {
executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
scanForExpiredSessions();
}
}, 30, 30, TimeUnit.SECONDS);
}
private void scanForExpiredSessions() {
for (Map.Entry<String, Long> entry : sessionIdToLastPingTime.entrySet()) {
if (Thread.currentThread().isInterrupted()) {
return;
}
final String sessionId = entry.getKey();
final Long lastPing = entry.getValue();
if (lastPing == null) {
// entry was removed from the map by another thread
continue;
}
if (System.currentTimeMillis() > lastPing + EXPIRATION_MILLIS) {
sessionIdToLastPingTime.remove(sessionId);
try {
expireSession(sessionId);
} catch (Exception e) {
// production code should use a logger
e.printStackTrace();
}
}
}
}
private void expireSession(String sessionId) {
// production code should use a logger
System.out.println("client stopped pinging for session " + sessionId);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
String sessionId = req.getSession().getId();
sessionIdToLastPingTime.put(sessionId, System.currentTimeMillis());
}
@Override
public void destroy() {
executor.shutdownNow();
try {
// this is optional, but may prevent Tomcat from reporting the webapp as a memory-leaker
executor.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// production code should use a logger
System.out.println("interrupted while waiting for executor to shut down");
Thread.currentThread().interrupt();
}
}
}
答案 2 :(得分:0)
琐碎的案例:
答案 3 :(得分:0)
在服务器端,您可以使用java Date类在上次收到ping时存储。
long lastRecv = System.getTimeMillis();
在另一个循环中(可能是另一个定期检查所有已知客户端数组的线程),您将检查lastRecv时间码并立即将其与之比较。
if( date.getTime() - lastRecv > TIMEOUT_IN_MS )
// Handle user timing out
每次收到新的ping时,只需将lastRecv时间更新为新的当前时间。您将知道用户何时超时,因为您有一些预设阈值(例如TIMEOUT_IN_MS)小于您上次看到ping进入的时间。
显然,你必须修改我在这里提供的示例代码,以反映客户端数量,线程模型和数据模型,但我认为它足以满足这个想法。
答案 4 :(得分:0)
也许使用会话超时较短的HttpSessionListener?
http://docs.oracle.com/javaee/5/api/javax/servlet/http/HttpSessionListener.html