我使用websockets有几个问题:
-
java.io.IOException: Broken Pipe
- 客户端没有收到消息
TL;博士
我想知道的主要事情:
- 请列出客户端关闭连接的所有可能情况(除了刷新或关闭选项卡)。
- 除了服务器通过断开的连接向客户端发送消息外,还会发生管道断开异常吗?如果是,那么是怎么做的?
- 服务器虽然发送了心跳,但不发送消息的可能情况是什么?(当发生这种情况时,我需要重新启动应用程序才能再次工作。这是一个糟糕的解决方案,因为它已经在生产中。
我有一个使用
websockets
的SpringMVC
项目;SockJS
客户端和org.springframework.web.socket.handler.TextWebSocketHandler
服务器端
服务器端生成JSON
并发送给客户端。有时,我得到一个java.io.IOException: Broken Pipe
。我谷歌/stackoverflow很多,发现太多的东西我不明白,但原因可能是连接是关闭的客户端和服务器仍然发送消息(例如,心跳)。这听起来可以吗?出现这种例外的其他原因是什么?客户端关闭连接的原因是什么(除了刷新或关闭选项卡)?
而且,有时客户端没有从服务器获得任何消息,尽管服务器应该发送它们。我在发送消息之前和之后分别记录日志,两条日志语句都被打印出来。有人知道为什么会发生这种情况吗?我在Chrome的控制台日志中没有错误。刷新页面不工作,我需要重新启动spring项目…
如果你需要更多信息,请留下评论。
客户端
function connect() {
var socket = new SockJS('/ws/foo');
socket.onopen = function () {
socket.send(fooId); // ask server for Foo with id fooId.
};
socket.onmessage = function (e) {
var foo = JSON.parse(e.data);
// Do something with foo.
};
}
服务器端
服务
@Service
public class FooService implements InitializingBean {
public void updateFoo(...) {
// Update some fields of Foo.
...
// Send foo to clients.
FooUpdatesHandler.sendFooToSubscribers(foo);
}
}
WebSocketHandler
public class FooUpdatesHandler extends ConcurrentTextWebSocketHandler {
// ConcurrentTextWebSocketHandler taken from https://github.com/RWTH-i5-IDSG/BikeMan (Apache License version 2.0)
private static final Logger logger = LoggerFactory.getLogger(FooUpdatesHandler.class);
private static final ConcurrentHashMap<String, ConcurrentHashMap<String, WebSocketSession>> fooSubscriptions =
new ConcurrentHashMap<>();
public static void sendFooToSubscribers(Foo foo) {
Map<String, WebSocketSession> sessionMap = fooSubscriptions.get(foo.getId());
if (sessionMap != null) {
String fooJson = null;
try {
fooJson = new ObjectMapper().writeValueAsString(foo);
} catch (JsonProcessingException ignored) {
return;
}
for (WebSocketSession subscription : sessionMap.values()) {
try {
logger.info("[fooId={} sessionId={}] Sending foo...", foo.getId(), subscription.getId());
subscription.sendMessage(new TextMessage(fooJson));
logger.info("[fooId={} sessionId={}] Foo send.", foo.getId(), subscription.getId());
} catch (IOException e) {
logger.error("Socket sendFooToSubscribers [fooId={}], exception: ", foo.getId(), e);
}
}
}
}
}
只是一个有根据的猜测:检查你的网络设备。可能是配置错误的防火墙终止了这些连接;或者更糟糕的是,网络设备损坏导致连接终止。如果您的服务器有多个网卡(很可能是这种情况),那么使用这些网卡时也可能出现一些配置错误,或者通过不同的网卡连接到服务器。
如果此问题意外发生,则可能是您的任何缓存存在问题-请检查spring或SocksJS是否有自己的套接字交互缓存
这是否发生在您的设备上(或您控制的设备上)?
另外,我可以建议你使用一些网络数据包分析器,如wireshark。使用此工具,您将看到当前网络活动"在线"
一些外部原因可能会破坏连接而没有正确地停止它(如果没有连接检查你就无法管理它):
- 设备暂停/定时关机
- 网络故障
- 浏览器出现错误关闭
我认为这只是破坏连接的全部可能原因中的一小部分。