Spring websockets损坏的管道和客户端没有收到消息

J. *_*ans 11 java spring websocket sockjs

我在使用websockets时遇到一些问题:

  • java.io.IOException: Broken Pipe
  • 客户端不接收消息
    TL; DR

我想知道的主要事项:

  • 请列出客户端关闭连接的所有可能方案(除了刷新或关闭选项卡).
  • 除了服务器通过断开的连接向客户端发送消息之外,是否会发生损坏的管道异常?如果是,那怎么样?
  • 尽管服务器确实发送了心跳,但服务器不发送消息的可能情况有哪些?(当发生这种情况时,我需要重新启动应用程序才能再次使用.这是一个糟糕的解决方案,因为它已经在生产中.)


我有一个SpringMVC项目使用websockets; SockJS客户端和org.springframework.web.socket.handler.TextWebSocketHandler服务器端.

A JSON生成服务器端并发送给客户端.有时,我得到了java.io.IOException: Broken Pipe.我google/StackOverflowed很多,发现太多我不理解的东西,但原因可能是连接是关闭客户端而服务器仍然发送消息(例如,心跳).听起来不错吗?这种例外的其他原因是什么?客户端关闭连接的原因是什么(刷新或关闭选项卡除外)?

此外,有时客户端不会从服务器获取任何消息,尽管服务器应该发送它们.我在发送消息之前和之后进行登录,并打印两个日志语句.有谁知道为什么会发生这种情况?我在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.
    };
}
Run Code Online (Sandbox Code Playgroud)

服务器端
服务

@Service
public class FooService implements InitializingBean {
    public void updateFoo(...) {
        // Update some fields of Foo.
        ...
        // Send foo to clients.
        FooUpdatesHandler.sendFooToSubscribers(foo);
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mr.*_*dar 1

只是一个有根据的猜测:检查您的网络设备。可能是防火墙配置错误而终止了这些连接;或者更糟糕的是,网络设备损坏导致连接终止。如果您的服务器有多个 NIC(很可能是这种情况),则使用这些 NIC 或通过不同 NIC 连接到服务器时也可能存在一些配置错误。