我正在尝试实现asp.net core的websocket,但发现我无法使服务器ping客户端以任何时间间隔进行确认。 浏览器从不注册任何ping帧。 出于测试目的,我基本上是在复制Microsoft的代码,因此我的代码类似于此演示: https : //docs.microsoft.c ...
提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
现在,我在 Tomcat 7 上运行了一个非常简单的 WebSocket ,只有一个心跳。 它每 30 秒向每个 session 发送一个 ping,并在 3 个错过的乒乓球后关闭 session。 我遇到的问题是服务器正确发送了第一个 ping,但之后没有发送任何。 发送实际 ping 的代码正在执行,但从分析网络来看,没有发送 ping。 它也没有抛出任何异常。 另外,我之前在 Tomcat 9 上运行它,但没有出现这个问题。
这是心跳的代码
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.websocket.PongMessage;
import javax.websocket.Session;
public class HeartbeatManager {
private static final ByteBuffer DATA = ByteBuffer.wrap("heartbeat".getBytes());
private static final long HEARTBEAT_DELAY_MS = 30 * 1000;
private static final long MISSED_PONG_LIMIT = 3;
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
private Map<String, Heartbeat> sessionHeartbeats = new HashMap<String, Heartbeat>();
public void start(Session session) {
Heartbeat heartbeat = new Heartbeat(session);
heartbeat.future = executor.scheduleAtFixedRate(heartbeat, HEARTBEAT_DELAY_MS, HEARTBEAT_DELAY_MS, TimeUnit.MILLISECONDS);
Heartbeat oldHeartbeat = sessionHeartbeats.put(session.getId(), heartbeat);
if (oldHeartbeat != null) {
oldHeartbeat.future.cancel(true);
}
}
public void stop(Session session) {
Heartbeat heartbeat = sessionHeartbeats.remove(session.getId());
if (heartbeat != null) {
heartbeat.future.cancel(true);
}
}
public void onPong(Session session, PongMessage message) {
Heartbeat heartbeat = sessionHeartbeats.get(session.getId());
if (heartbeat != null) {
heartbeat.onPong(message);
}
}
private class Heartbeat implements Runnable {
private final Object LOCK = new Object();
private ScheduledFuture<?> future;
private Session session;
private int missedPongs;
private boolean pong = true;
public Heartbeat(Session session) {
this.session = session;
}
public void onPong(PongMessage message) {
if (Arrays.equals(DATA.array(), message.getApplicationData().array())) {
synchronized (LOCK) {
pong = true;
missedPongs = 0;
}
}
}
@Override
public void run() {
synchronized (LOCK) {
if (!pong && ++missedPongs >= MISSED_PONG_LIMIT) {
try {
session.close();
} catch (IOException e) {
}
} else {
pong = false;
try {
session.getBasicRemote().sendPing(DATA);
} catch (IOException e) {
}
}
}
}
}
}
如果有帮助,这里是 ServerEndpoint
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.PongMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/test")
public class Test {
private static HeartbeatManager m = new HeartbeatManager();
@OnOpen
public void onOpen(Session session) {
m.start(session);
}
@OnMessage
public void onMessage(Session session, PongMessage message) {
m.onPong(session, message);
}
@OnClose
public void onClose(Session session) {
m.stop(session);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.