Java 如何关闭 WebSocketContainer / WebSocketClient / Jetty 客户端?
How do you close WebSocketContainer / WebSocketClient / Jetty client in Java?
我正在尝试使用 Jetty 的 WebSocket 客户端,但应用程序只会卡在那里,不会退出。没什么好看的...
public class TestEndPoint extends Endpoint {
private Session sess;
public TestEndPoint(URI endpoint) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpoint);
}
public void close() {
try {
this.sess.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
...
}
我正在将其连接到我的 PHP Ratchet WS,没有什么特别的,没有特殊的逻辑,我只是在客户端连接时打印 open
,在客户端断开连接时打印 close
。
然后我运行这样:
public static void main(String[] args) {
try {
TestEndPoint test = new TestEndPoint(new URI("ws://localhost:8080/test"));
Thread.sleep(5000);
test.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
我可以看到我的 WS 会打印 "close",但是 Java 应用程序永远不会退出。所以我进行了线程转储,发现 jetty
东西卡在了某些 QueuedThreadPool
...
中
一些线程转储:
"WebSocketContainer@1735934726-15" #15 daemon prio=5 os_prio=0 tid=0x0000000016cdf000 nid=0x1c5c runnable [0x000000001763e000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296)
at sun.nio.ch.WindowsSelectorImpl$SubSelector.access0(WindowsSelectorImpl.java:278)
at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000ebf678c8> (a sun.nio.ch.Util)
- locked <0x00000000ebf68128> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000ebf67d40> (a sun.nio.ch.WindowsSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:101)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.select(ManagedSelector.java:346)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.produce(ManagedSelector.java:299)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:179)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:243)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:679)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:597)
at java.lang.Thread.run(Thread.java:748)
"WebSocketContainer@1735934726-14" #14 daemon prio=5 os_prio=0 tid=0x0000000016cc7000 nid=0xfb4 waiting on condition [0x000000001753f000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ebde1df8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:392)
at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:571)
at org.eclipse.jetty.util.thread.QueuedThreadPool.access0(QueuedThreadPool.java:50)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:634)
at java.lang.Thread.run(Thread.java:748)
最后,我在 Gradle;
中使用了 Jetty
的这些版本
compile group: 'org.eclipse.jetty.websocket', name: 'websocket-api', version: '9.4.6.v20170531'
compile group: 'org.eclipse.jetty.websocket', name: 'websocket-client', version: '9.4.6.v20170531'
compile group: 'org.eclipse.jetty.websocket', name: 'javax-websocket-client-impl', version: '9.4.7.v20170914'
关闭网络套接字或客户端的正确方法是什么?
经过多次谷歌搜索和查看许多示例代码后,您似乎需要手动 stop
将 WebSocketContainer
强制转换为 org.eclipse.jetty.util.component.LifeCycle
!
为了停止 Jetty 的 WebSocket 客户端,您需要通过 Session
或 WebSocketContainer
本身执行以下操作。所以在我的 close
函数中:
try {
Session sess = getSession();
WebSocketContainer container = sess.getContainer();
// Need to cast the container to Jetty's LifeCycle
if(container != null && container instanceof LifeCycle) {
Logger.debug("Stopping Jetty's WebSocket Client");
((LifeCycle) container).stop();
}
sess.close();
} catch (Exception e) {
Logger.error(e);
}
在 Jetty 的网站上没有任何文档 (http://www.eclipse.org/jetty/documentation/9.4.7.v20170914/)
我正在尝试使用 Jetty 的 WebSocket 客户端,但应用程序只会卡在那里,不会退出。没什么好看的...
public class TestEndPoint extends Endpoint {
private Session sess;
public TestEndPoint(URI endpoint) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpoint);
}
public void close() {
try {
this.sess.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
...
}
我正在将其连接到我的 PHP Ratchet WS,没有什么特别的,没有特殊的逻辑,我只是在客户端连接时打印 open
,在客户端断开连接时打印 close
。
然后我运行这样:
public static void main(String[] args) {
try {
TestEndPoint test = new TestEndPoint(new URI("ws://localhost:8080/test"));
Thread.sleep(5000);
test.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
我可以看到我的 WS 会打印 "close",但是 Java 应用程序永远不会退出。所以我进行了线程转储,发现 jetty
东西卡在了某些 QueuedThreadPool
...
一些线程转储:
"WebSocketContainer@1735934726-15" #15 daemon prio=5 os_prio=0 tid=0x0000000016cdf000 nid=0x1c5c runnable [0x000000001763e000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296)
at sun.nio.ch.WindowsSelectorImpl$SubSelector.access0(WindowsSelectorImpl.java:278)
at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000ebf678c8> (a sun.nio.ch.Util)
- locked <0x00000000ebf68128> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000ebf67d40> (a sun.nio.ch.WindowsSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:101)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.select(ManagedSelector.java:346)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.produce(ManagedSelector.java:299)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:179)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:243)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:679)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:597)
at java.lang.Thread.run(Thread.java:748)
"WebSocketContainer@1735934726-14" #14 daemon prio=5 os_prio=0 tid=0x0000000016cc7000 nid=0xfb4 waiting on condition [0x000000001753f000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ebde1df8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:392)
at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:571)
at org.eclipse.jetty.util.thread.QueuedThreadPool.access0(QueuedThreadPool.java:50)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:634)
at java.lang.Thread.run(Thread.java:748)
最后,我在 Gradle;
中使用了Jetty
的这些版本
compile group: 'org.eclipse.jetty.websocket', name: 'websocket-api', version: '9.4.6.v20170531'
compile group: 'org.eclipse.jetty.websocket', name: 'websocket-client', version: '9.4.6.v20170531'
compile group: 'org.eclipse.jetty.websocket', name: 'javax-websocket-client-impl', version: '9.4.7.v20170914'
关闭网络套接字或客户端的正确方法是什么?
经过多次谷歌搜索和查看许多示例代码后,您似乎需要手动 stop
将 WebSocketContainer
强制转换为 org.eclipse.jetty.util.component.LifeCycle
!
为了停止 Jetty 的 WebSocket 客户端,您需要通过 Session
或 WebSocketContainer
本身执行以下操作。所以在我的 close
函数中:
try {
Session sess = getSession();
WebSocketContainer container = sess.getContainer();
// Need to cast the container to Jetty's LifeCycle
if(container != null && container instanceof LifeCycle) {
Logger.debug("Stopping Jetty's WebSocket Client");
((LifeCycle) container).stop();
}
sess.close();
} catch (Exception e) {
Logger.error(e);
}
在 Jetty 的网站上没有任何文档 (http://www.eclipse.org/jetty/documentation/9.4.7.v20170914/)