关闭 websocket 后得到 "Handshake response not received."

getting "Handshake response not received." after closing websocket

我正在使用 tyrus websocket 客户端 (1.11) 连接到 websocket。

compile 'org.glassfish.tyrus:tyrus-client:1.+'
compile 'org.glassfish.tyrus:tyrus-container-grizzly-client:1.+'

我是 运行 本地 wscat 服务器 (wscat --listen) 来测试我的连接。

我的客户端所做的是连接到 websocket,发送一个文本字符串,然后是二进制加载 (0xb5,0xb2,0xb1,0xb0,0xb1,0xb2,0xc6),然后是另一个字符串,然后断开连接。

这是服务器看到的(并且正是我所期望的):

listening on port 8666 (press CTRL+C to quit)
client connected
< Ohai, Server!
< �������
< Bye, Server!
disconnected

注意:实体做连接,Monkey class extends Thread and runs asynchronously so some日志行可能乱序。

不过,客户端的情况并不那么美好。虽然日志同意建立连接、发送三个块并关闭连接,但它也给了我一个堆栈跟踪,表明连接失败,因为没有收到握手响应(见完整日志 here):

...
[org.glassfish.tyrus.client.TyrusClientEngine] FINE: > Session af609b3f-2978-453f-9758-10351d5ed2af [43 ms]: Sending handshake request:
> GET ws://127.0.0.1:8666
> Connection: Upgrade
> Host: 127.0.0.1:8666
> Origin: 127.0.0.1:8666
> Sec-WebSocket-Key: pGNihDxLIbQqcxvMTBERSQ==
> Sec-WebSocket-Protocol: binary
> Sec-WebSocket-Version: 13
> Upgrade: websocket

[org.glassfish.tyrus.client.TyrusClientEngine] FINE: < Session af609b3f-2978-453f-9758-10351d5ed2af [324 ms]: Received handshake response: 
< 101
< connection: Upgrade
< sec-websocket-accept: EZjq5dEOzWz2q46tKtNlVD8K+mk=
< sec-websocket-protocol: binary
< upgrade: websocket
...
[MONKEY_0] FINER: Session 'af609b3f-2978-453f-9758-10351d5ed2af' opened
[RUNNER] INFO: MONKEY_0 connected
[MONKEY_0] FINER: Sending messages...
[MONKEY_0] FINER: Saying Hi...
[org.glassfish.tyrus.core.TyrusRemoteEndpoint] FINEST: > Session af609b3f-2978-453f-9758-10351d5ed2af [335 ms]: Sending text message: Ohai, Server!
...
[MONKEY_0] FINER: Said Hi. Now Sending binary data...
[org.glassfish.tyrus.core.TyrusRemoteEndpoint] FINEST: > Session af609b3f-2978-453f-9758-10351d5ed2af [342 ms]: Sending binary message
[MONKEY_0] FINER: Binary sent. Saying Bye...
[org.glassfish.tyrus.core.TyrusRemoteEndpoint] FINEST: > Session af609b3f-2978-453f-9758-10351d5ed2af [344 ms]: Sending text message: Bye, Server!
[MONKEY_0] FINER: Messages sent.
[MONKEY_0] INFO: Closing socket.
[org.glassfish.tyrus.core.TyrusRemoteEndpoint] FINE: Close public void close(CloseReason cr): CloseReason[1000,Bye]
...
[MONKEY_0] FINER: Session 'af609b3f-2978-453f-9758-10351d5ed2af' closed (Bye)
[RUNNER] INFO: MONKEY_0 disconnected
[MONKEY_0] SEVERE: Unable to connect to 'ws://127.0.0.1:8666'
javax.websocket.DeploymentException: Handshake response not received.
    at org.glassfish.tyrus.client.ClientManager.run(ClientManager.java:691)
    at org.glassfish.tyrus.client.ClientManager.run(ClientManager.java:712)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:866)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:511)
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:373)
    at com.redacted.webmonkey.monkey.Monkey.connect(Monkey.java:90)
    at com.redacted.webmonkey.monkey.Monkey.run(Monkey.java:47)
Caused by: java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1039)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1328)
    at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:277)
    at org.glassfish.tyrus.client.ClientManager.run(ClientManager.java:666)
    ... 9 more
...
[RUNNER] SEVERE: 'MONKEY_0' failed. Error: Cannot connect
...

为什么明显是第二次连接尝试? 这是怎么回事?

我输入了一些时间戳以查看实际情况:

Session s = null;
try {
    LOG.d("(%d) attempting to connect", System.currentTimeMillis());
    WebSocketContainer wsc = ContainerProvider.getWebSocketContainer();
    s = wsc.connectToServer(this, uri);
    LOG.d("(%d) Connected", System.currentTimeMillis());
} catch (Exception e) {
    LOG.e("(%d) Unable to connect to '%s'", System.currentTimeMillis(), uri);
    e.printStackTrace();
}

LOG.d("(%d) Session id : %s", System.currentTimeMillis(), s == null ? null : s.getId());
return s != null;

我实际收到的信息表明我无法连接(但我发送了这些消息,不是吗?)

[MONKEY_0] FINER: (1441396510763) attempting to connect
[MONKEY_0] FINER: (1441396511068) Session '4c0b1f6e-de7e-471d-a801-f807895c4a0b' opened
[MONKEY_0] FINER: (1441396511079) Session '4c0b1f6e-de7e-471d-a801-f807895c4a0b' closed (Bye)
[MONKEY_0] SEVERE: (1441396511080) Unable to connect to 'ws://127.0.0.1:8666'
[MONKEY_0] FINER: (1441396511081) Session id : null

我与 ws 进行交易时,连接调用似乎被阻止了。它是否假定存在错误,因为连接在 onOpen 回调结束时关闭?

好的,看来 onOpen 回调期间关闭会话 确实是 为什么 WebsocketContainer 感到困惑并认为连接失败的原因. 只是为了测试,我使用 getBasicRemote() (同步)发送消息,然后在完成所有操作后关闭套接字。 我切换到使用 getAsyncRemote() 并在所有消息发送后关闭,现在 wsc 正确报告连接成功。

我想知道阻塞回调是否是个好主意?

不要在 onOpen(Session session, EndpointConfig endpointConfig) 中调用 Thread.sleep()。使用自己的线程发送消息,ClientManager.connect return Session对象,使用此对象发送消息。