当前位置: 首页 > 知识库问答 >
问题:

Netty websocket客户端在Android设备上运行时从不发送websocket消息

白翔
2023-03-14

将运行在JDK6-8下的现有web套接字客户端部署到Android(API 19)会使客户端无法将web套接字帧发送到服务器。

发生正常的http升级,并且存在http连接,但使用ChannelHandlerContext发送的任何消息都不存在。writeAndFlush()永远不要越界(我已经在服务器上与Wireshark确认了这一点)。

//从IClientConnection的实现
public void sendBinaryMessage(FastByteArrayOutputStream)抛出异常{this.lock();

    try {

        if (_logger.isTraceEnabled()) {
            System.out.println("Sending binary Message:\n" + HexDump.hexDump(stream.toByteArray(), 20));
        }

        // recommended use when you already have an existing byte[] is to
        // create the ByteBuf using Unpooled, not the PooledByteBufAllocator
        ByteBuf buffer = Unpooled.wrappedBuffer(stream.getByteArray(), 0, stream.getSize());

        BinaryWebSocketFrame binaryMessage = new BinaryWebSocketFrame(buffer);
        String st = StringUtilities.toHexString(buffer.array());
        _logger.debug("SENDING AUTH MESSAGE:" + st);
        ChannelFuture promise = this.getWebSocket().writeAndFlush(binaryMessage);
        promise.await();
        _logger.debug("MESSAGE SENT");
    } finally {
        this.unlock();
    }
}

日志输出

I/System.out: 14:24:18.605 [Client-EndpointMonitor-1] DEBUG io.netty.util.NetUtil - Loopback interface: lo (lo, ::1%1)
I/System.out: 14:24:18.615 [Client-EndpointMonitor-1] DEBUG io.netty.util.NetUtil - /proc/sys/net/core/somaxconn: 128
I/System.out: 14:24:18.738 [Client-EndpointMonitor-1] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 90:68:c3:ff:fe:f1:ed:5c (auto-detected)
I/System.out: 14:24:18.751 [Client-EndpointMonitor-1] DEBUG io.netty.util.internal.ThreadLocalRandom - -Dio.netty.initialSeedUniquifier: 0x63ddb0bd5ba71d45
I/System.out: 14:24:18.835 [Client-EndpointMonitor-1] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: unpooled
I/System.out: 14:24:18.842 [Client-EndpointMonitor-1] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0
I/System.out: 14:24:18.850 [Client-EndpointMonitor-1] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
I/System.out: 14:24:19.127 [NettyClient-NIO-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
D/com.thingworx.sdk.android.activity.ThingworxActivity: Waiting for initial connection...
I/System.out: 14:24:19.135 [NettyClient-NIO-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
I/System.out: 14:24:19.145 [NettyClient-NIO-1] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@2bea8c32
I/System.out: 14:24:19.595 [NettyClient-NIO-1] DEBUG com.thingworx.communications.client.connection.netty.NettyClientConnectionFactory - Adding compression handler to pipeline
I/System.out: 14:24:19.606 [NettyClient-NIO-1] DEBUG io.netty.handler.codec.compression.ZlibCodecFactory - -Dio.netty.noJdkZlibDecoder: true
I/System.out: 14:24:19.615 [NettyClient-NIO-1] DEBUG io.netty.handler.codec.compression.ZlibCodecFactory - -Dio.netty.noJdkZlibEncoder: false
D/com.thingworx.sdk.android.activity.ThingworxActivity: Waiting for initial connection...
I/System.out: 14:24:20.501 [NettyClient-NIO-1] DEBUG com.thingworx.communications.client.connection.netty.ThingworxClientConnectionHandler - WebSocket Channel is connected [is open: true]
D/com.thingworx.sdk.android.activity.ThingworxActivity: Waiting for initial connection...
I/System.out: 14:24:21.144 [NettyClient-NIO-1] DEBUG io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker13 - WebSocket version 13 client handshake key: AAX2bRU+jf63Fhyik0HAEg==, expected response: DOFv14sfAg0+tQcv2kuDguaF1Sw=
I/System.out: 14:24:21.190 [NettyClient-NIO-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
I/System.out: 14:24:21.198 [NettyClient-NIO-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
I/System.out: 14:24:21.205 [NettyClient-NIO-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 16
I/System.out: 14:24:21.213 [NettyClient-NIO-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
I/System.out: 14:24:21.830 [NettyClient-NIO-1] DEBUG com.thingworx.communications.client.connection.netty.ThingworxClientConnectionHandler - [ClientHandler: 911311818] Client websocket handshake is complete
I/System.out: 14:24:21.847 [Client-EndpointMonitor-1] INFO com.thingworx.communications.client.endpoints.ClientCommunicationEndpoint - Preparing new Connection Authentication Request: DispatchingClientEndpoint [id: 0, isConnected: false, open connections: 0, max connections: 1]
I/System.out: 14:24:21.864 [Client-EndpointMonitor-1] DEBUG com.thingworx.communications.common.endpoints.CommunicationEndpoint - Sending connection authentication message, waiting for response [sync key: 1, message: AuthRequestMessage [requestId: 1, endpointId: -1, sessionId: -1, method: AUTHREQUEST]]
D/com.thingworx.sdk.android.activity.ThingworxActivity: Waiting for initial connection...
D/com.thingworx.sdk.android.activity.ThingworxActivity: Waiting for initial connection...
I/System.out: 14:24:22.694 [Client-EndpointMonitor-1] DEBUG com.thingworx.communications.client.connection.netty.NettyClientConnection - SENDING AUTH MESSAGE:011400000001ffffffffffffffff0001066170704b65792461626630333663322d373030392d343436322d386139362d363033366565376562613533
D/com.thingworx.sdk.android.activity.ThingworxActivity: Waiting for initial connection...
I/Choreographer: Skipped 206 frames!  The application may be doing too much work on its main thread.
I/System.out: 14:24:26.794 [Client-EndpointMonitor-1] DEBUG com.thingworx.communications.client.connection.netty.NettyClientConnection - MESSAGE SENT

请注意,发送的消息是从writeAndFlush()上的promise返回的,该promise返回true

就预期的结果而言,我希望二进制websocket消息通过网络发出,但它从来没有发出过。

共有1个答案

鲁俊友
2023-03-14

我有一个答案。

事实证明,在我未来的promise中,有一个类加载异常正在被吞噬。因为没有记录类加载异常,所以在我看来,好像没有发送my消息。

这是个例外:

Caused by: io.netty.handler.codec.EncoderException: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/jcraft/jzlib/Deflater;
    at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:107)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:716)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:708)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:791)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:701)

现在很明显,只有禁用websocket压缩(至少在短期内)才能发送websocket流量。

我没有正确处理promise返回状态。

public void waitForChannelCompletion(ChannelFuture future, String operationMessage) throws IOException {
    future.awaitUninterruptibly();

    // Now we are sure the future is completed.
    if (future.isDone()) {
        if (future.isCancelled()) {
            String errorMsg = String.format("Netty IO Operation has been cancelled [operation: %s]", operationMessage);
            throw new IOException(errorMsg);
        } else if (future.isSuccess() == false) {
            String errorMsg = String.format("Netty IO Operation failed [operation: %s]", operationMessage);
            throw new IOException(errorMsg, future.cause());
        }
    } else {
        // future should be done, otherwise there's a problem
        String errorMsg = String.format("Netty IO Operation is not done [operation: %s]", operationMessage);
        throw new IOException(errorMsg);
    }
}
        ChannelFuture promise = this.getWebSocket().writeAndFlush(binaryMessage);
        waitForChannelCompletion(promise,"MESSAGE SENT");

希望这能让其他人免于类似的问题。

 类似资料:
  • 我会尽量解释我的问题,而不附加任何代码,我认为这是不必要的。好的,我有一个JS格式的websocket客户端,它连接到我的java服务器。握手完成,连接的处理程序在客户机上被调用,所以我向服务器发送一条消息,读取该消息。然后,消息被反转并发送回客户机,但不会调用客户机MessageReceived处理程序或任何其他处理程序。 这是我发送给客户的信息: 我认为问题一定出在第一个字节上。我写"b[0]

  • 我正在运行一个Autobahn/Twisted python websocket服务器,但我在向客户机发送消息时遇到了问题。它似乎只在客户端向它发送消息时才向客户端发送消息。由于某种原因,如果我想将消息强制输出到已连接的客户端,那么消息就会卡在队列中,直到任何客户端向我发送消息。此时,所有排队的消息都发送到所有客户端。 我能够在python Autobahn/Twisted websocket服务

  • 我正在通过在WebSocketClientFlow上遵循doc来尝试客户端websocket。

  • 问题内容: 这段代码一切正常(将其缩短以便更好地阅读)。 当向服务器发送请求时,服务器会立即响应他。但是,其他客户端看不到响应消息。 因此,我想进一步说明:当客户端向服务器发送请求时,服务器将响应所有客户端,以便所有客户端都能看到消息。 我怎样才能做到这一点?有任何示例或不错的入门教程吗? 提前致谢! 服务器: 问题答案: 您必须使用连接池将消息广播到所有连接。您可以将其用作教程/示例http:/

  • 在文档的socket.io客户端套接字部分http://socket.io/docs/client-api/#io#socket指的是套接字文档,这意味着服务器套接字对象和客户端套接字对象是相同的。

  • 我后来理解对了。实际上,我需要一条来自android客户端的MQTT消息发送到所有其他客户端,所以我想在消息正文中包含publish关键字,这是非常错误的。MQTT本身将接收到的消息发送给所有提供的客户端,如果客户端订阅了该主题的话。