首页 > 解决方案 > Okhttp websocket 预期 HTTP 101 响应,但使用 Spring Boot 服务器时为“400”

问题描述

我正在开发一个带有 Spring Boot 服务器的 Android 应用程序。

因此,我使用 OkHttp 从我的 Android 应用程序到使用 Stomp 的 Spring Boot 服务器打开一个 WebSocket 连接。

当 WebSocket 连接因服务器中引发的某些异常而关闭并且我尝试重新连接时,Expected HTTP 101 response but was '400 '出现错误。

出于测试目的,我在 Android 应用程序向服务器发送 SEND 帧时抛出异常。

所以这个测试是这样的

  1. 发送 WebSocket 升级请求
  2. 一旦 WebSocket 连接打开,发送 CONNECT Stomp 请求
  3. 然后,发送 SUBSCRIBE Stomp 请求订阅队列
  4. 然后,在 SEND St​​omp Frame 中发送消息,然后服务器抛出异常
  5. 服务器将响应 ERROR Stomp 帧并关闭 WebSocket 连接。
  6. 我尝试通过步骤 1-3 重新连接

这是用于测试的代码。

当我第一次启动我的 Android 应用程序时,它会向服务器发送 WebSocket 请求,如下所示。我编造了 IP 地址,但在我的实际应用程序中,我使用了正确的 IP 地址。

val webSocketRequest = Request.Builder().url("199.166.1.100:8081/websocket").build()
socket = okHttpClient.newWebSocket(webSocketRequest, this)

WebSocket 请求如下所示

Request{method=GET, url=http://199.166.1.100:8081/websocket, tags={}}

然后,服务器发送以下响应并调用 onOpen() 函数,这意味着握手工作正常。

Response{protocol=http/1.1, code=101, message=, url=http://199.166.1.100:8081/websocket}

在 onOpen() 函数中,我向服务器发送 Stomp CONNECT 请求,服务器响应 CONNECTED,然后我向队列发送 SUBSCRIBE 请求。到目前为止,一切正常。

我已向 StompMessageBorker 添加了一个拦截器,以便为 SEND 请求引发异常,如下所示

    public Message<?> preSend(Message<?> message, @NonNull MessageChannel channel) {
        StompHeaderAccessor stompHeaderAccessor = StompHeaderAccessor.wrap(message);
        StompCommand stompCommand = stompHeaderAccessor.getCommand();
        
        if (StompCommand.SEND.equals(stompCommand))
            throw new RuntimeException();

        return message;
    }

因此,我在 SEND St​​omp 框架中发送消息,当RuntimeException抛出该消息时,服务器会向 Android 应用程序发送 ERROR Stomp Frame 或响应,并调用 OkHttp Websocket 的 onClosing() 和 onClosed() 函数,这意味着WebSocket 连接已关闭。

这就是问题所在,在关闭 WebSocket 连接后,我尝试使用以下函数重新连接 WebSocket,并且基本上经历了相同的过程,发送 CONNECT 请求,然后发送 SUBSCRIBE 请求。

override suspend fun reconnect() {
    socket?.close(1000, null)
    val webSocketRequest = Request.Builder().url("199.166.1.100:8081/websocket").build()
    socket = okHttpClient.newWebSocket(webSocketRequest, this)
    
} 

但我得到Expected HTTP 101 response but was '400 '了,甚至没有调用 onOpen() 函数,我猜握手有一些问题。

通过执行此测试,我注意到了几件事。

  1. 前三个或四个重新连接请求按预期工作,调用了 onOpen() 函数,我也可以订阅队列。但是在 3 或 4 次之后,我开始收到此错误Expected HTTP 101 response but was '400 ',从那时起,每个重新连接请求都会收到相同的错误。

  2. 一旦我得到这个Expected HTTP 101 response but was '400 ',重新启动我的 Spring Boot 服务器并没有帮助,但是如果重新启动我的 Android 应用程序,那么我可以连接 Websocket。但是在通过发送引发异常的消息触发 3 或 4 次断开连接后,我最终得到了相同的错误。

大家对这个问题有什么想法吗?还是我做错了?

断开 3 次或 4 次后如何建立 WebSocket 连接?

提前致谢。

===============更新=================================

我添加了一个HandshakeInterceptor以查看beforeHandshake().

显然,当我收到 101 响应时,beforeHandshake()调用了。

Response{protocol=http/1.1, code=101, message=, url=http://199.166.1.100:8081/websocket}

但是,当我收到 400 响应时

Expected HTTP 101 response but was '400 '

beforeHandshake()根本没有调用。为什么beforeHandshake()甚至没有调用,因为我从 Android 向服务器发送了握手请求?

===============更新=================================

让我让事情变得更容易。

我做了以下测试

  1. 运行 Spring Boot 服务器
  2. 启动安卓应用程序。
  3. WebSocket 连接成功。
  4. 重启 Spring Boot 服务器
  5. WebSocket 连接已关闭
  6. Android发送HTTP握手以重新连接WebSocket,我得到了Expected HTTP 101 response but was '400 '

我不确定为什么重新启动会使服务器表现不同。

标签: androidspring-bootwebsocketokhttp

解决方案


推荐阅读