Tyrus wss:// websocket 不通过 squid 代理
Tyrus wss:// websocket not passing through squid proxy
这是使用 Java 8、squid 3.1.2 和 tyrus-standalone-client-1.12.jar
实现 websocket。
更新:
它仍然不适用于 Tyrus。但是,问题似乎不在于 squid,因为当我使 Chrome 使用代理并在此处连接到 SO 时,到 wss://qa.whosebug.com
的连接通过 squid 代理并且工作正常。
我正在使用 javax.websocket client simple example 的已接受答案中给出的测试程序来尝试获取 squid 代理 运行。
但是,我已将其更改为使用 websockets.org 回显服务器,因此 URI 已从 wss://real.okcoin.cn:10440/websocket/okcoinapi
更改为 wss://echo.websocket.org
。
当我不使用代理时,测试程序在 wss://echo.websocket.org
和 ws://echo.websocket.org
上工作正常。
当我通过 -Dhttp.proxyHost
、-Dhttp.proxyPort
、-Dhttps.proxyHost
和 -Dhttps.proxyPort
指定 JVM 范围的代理时,ws://
URI 工作正常,但 wss://
一个没有。
我已经验证(使用 tcpdump)流量正在流向代理,测试程序正在向代理发送 CONNECT
,并且代理发回 Connection established
。但是,那时没有其他事情发生:
# tcpdump -n -l -s 0 -S -X 'host 172.16.99.15'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
17:21:45.361023 IP 172.16.99.21.36521 > 172.16.99.15.3128: S 1720321489:1720321489(0) win 14600 <mss 1460,sackOK,timestamp 1135431 0,nop,wscale 5>
0x0000: 4500 003c 5696 4000 4006 c5e0 ac10 6315 E..<V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 05d1 0000 0000 ..c....8f.......
0x0020: a002 3908 1e74 0000 0204 05b4 0402 080a ..9..t..........
0x0030: 0011 5347 0000 0000 0103 0305 ..SG........
17:21:45.361763 IP 172.16.99.15.3128 > 172.16.99.21.36521: S 1626710395:1626710395(0) ack 1720321490 win 14480 <mss 1460,sackOK,timestamp 1127109 1135431,nop,wscale 7>
0x0000: 4500 003c 0000 4000 4006 1c77 ac10 630f E..<..@.@..w..c.
0x0010: ac10 6315 0c38 8ea9 60f5 a17b 668a 05d2 ..c..8..`..{f...
0x0020: a012 3890 613d 0000 0204 05b4 0402 080a ..8.a=..........
0x0030: 0011 32c5 0011 5347 0103 0307 ..2...SG....
17:21:45.361789 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710396 win 457 <nop,nop,timestamp 1135431 1127109>
0x0000: 4500 0034 5697 4000 4006 c5e7 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 05d2 60f5 a17c ..c....8f...`..|
0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 5347 .....l........SG
0x0030: 0011 32c5 ..2.
17:21:45.407930 IP 172.16.99.21.36521 > 172.16.99.15.3128: P 1720321490:1720321613(123) ack 1626710396 win 457 <nop,nop,timestamp 1135442 1127109>
0x0000: 4500 00af 5698 4000 4006 c56b ac10 6315 E...V.@.@..k..c.
0x0010: ac10 630f 8ea9 0c38 668a 05d2 60f5 a17c ..c....8f...`..|
0x0020: 8018 01c9 1ee7 0000 0101 080a 0011 5352 ..............SR
0x0030: 0011 32c5 434f 4e4e 4543 5420 6563 686f ..2.CONNECT.echo
0x0040: 2e77 6562 736f 636b 6574 2e6f 7267 3a34 .websocket.org:4
0x0050: 3433 2048 5454 502f 312e 310d 0a48 6f73 43.HTTP/1.1..Hos
0x0060: 743a 2065 6368 6f2e 7765 6273 6f63 6b65 t:.echo.websocke
0x0070: 742e 6f72 670d 0a50 726f 7879 2d43 6f6e t.org..Proxy-Con
0x0080: 6e65 6374 696f 6e3a 206b 6565 702d 616c nection:.keep-al
0x0090: 6976 650d 0a43 6f6e 6e65 6374 696f 6e3a ive..Connection:
0x00a0: 206b 6565 702d 616c 6976 650d 0a0d 0a .keep-alive....
17:21:45.408347 IP 172.16.99.15.3128 > 172.16.99.21.36521: . ack 1720321613 win 114 <nop,nop,timestamp 1127121 1135442>
0x0000: 4500 0034 93b9 4000 4006 88c5 ac10 630f E..4..@.@.....c.
0x0010: ac10 6315 0c38 8ea9 60f5 a17c 668a 064d ..c..8..`..|f..M
0x0020: 8010 0072 c795 0000 0101 080a 0011 32d1 ...r..........2.
0x0030: 0011 5352 ..SR
17:21:45.423007 IP 172.16.99.15.3128 > 172.16.99.21.36521: P 1626710396:1626710435(39) ack 1720321613 win 114 <nop,nop,timestamp 1127124 1135442>
0x0000: 4500 005b 93ba 4000 4006 889d ac10 630f E..[..@.@.....c.
0x0010: ac10 6315 0c38 8ea9 60f5 a17c 668a 064d ..c..8..`..|f..M
0x0020: 8018 0072 bdab 0000 0101 080a 0011 32d4 ...r..........2.
0x0030: 0011 5352 4854 5450 2f31 2e30 2032 3030 ..SRHTTP/1.0.200
0x0040: 2043 6f6e 6e65 6374 696f 6e20 6573 7461 .Connection.esta
0x0050: 626c 6973 6865 640d 0a0d 0a blished....
17:21:45.423041 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710435 win 457 <nop,nop,timestamp 1135446 1127124>
0x0000: 4500 0034 5699 4000 4006 c5e5 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 064d 60f5 a1a3 ..c....8f..M`...
0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 5356 .....l........SV
0x0030: 0011 32d4 ..2.
17:22:15.649132 IP 172.16.99.21.36521 > 172.16.99.15.3128: F 1720321613:1720321613(0) ack 1626710435 win 457 <nop,nop,timestamp 1143003 1127124>
0x0000: 4500 0034 569a 4000 4006 c5e4 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 064d 60f5 a1a3 ..c....8f..M`...
0x0020: 8011 01c9 1e6c 0000 0101 080a 0011 70db .....l........p.
0x0030: 0011 32d4 ..2.
17:22:15.650241 IP 172.16.99.15.3128 > 172.16.99.21.36521: F 1626710435:1626710435(0) ack 1720321614 win 114 <nop,nop,timestamp 1134681 1143003>
0x0000: 4500 0034 93bb 4000 4006 88c3 ac10 630f E..4..@.@.....c.
0x0010: ac10 6315 0c38 8ea9 60f5 a1a3 668a 064e ..c..8..`...f..N
0x0020: 8011 0072 8c5b 0000 0101 080a 0011 5059 ...r.[........PY
0x0030: 0011 70db ..p.
17:22:15.650255 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710436 win 457 <nop,nop,timestamp 1143003 1134681>
0x0000: 4500 0034 569b 4000 4006 c5e3 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 064e 60f5 a1a4 ..c....8f..N`...
0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 70db .....l........p.
0x0030: 0011 5059 ..PY
并不是代理在 Java TLS 连接方面存在问题。如果我改为(仍然使用 Java 8)通过代理建立普通 HTTPS 连接(比如 https://www.google.com
),我会看到客户端发送相同的 CONNECT
和相同的 Connection established
被代理发回,但随后 TLS 握手等正常进行并且 request/response 正常完成。
坦率地说,我对正在发生的事情(或者更确切地说没有发生的事情)感到困惑。
我能够 100% 重现问题中描述的问题。我使用 Squid 版本 3.5.17 (Windows 10 64bit),
本地 Tomcat 使用带有 "echo" 网络套接字和 Java 7 的自签名证书(但我认为 Java 8 没有任何区别)。
当我使用 org.glassfish.tyrus.bundles:tyrus-standalone-client:1.11
而不是 1.12
时一切正常。
当我发现这个错误修复时,我决定使用以前的版本:
2015/Nov/13:Grizzly 传输无法通过 HTTP 代理打开 wss 连接
(github-commit).
1.11 版于 2015 年 6 月发布,1.12 版于 2015 年 9 月发布,我希望在 1.13 版中修复
(另见 pom history)。
的解决方案可能与 (2015/Aug/21) 有关。
供参考,1.12 的输出(硬编码超时为 30 秒
在 org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.CLIENT_SOCKET_TIMEOUT
中,因此您必须等待一段时间才能出现错误)。
05:07:25.514 [Grizzly(1) SelectorRunner] TRACE o.g.t.c.g.c.GrizzlyClientFilter - handleConnect
Using SSLEngineImpl.
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
05:07:25.651 [Grizzly(1)] DEBUG o.g.t.c.g.c.GrizzlyClientFilter - handleRead websocket: null content-size=0 headers=
HttpResponsePacket (
status=200
reason=Connection established
protocol=HTTP/1.1
content-length=-1
committed=false
headers=[]
)
javax.websocket.DeploymentException: Connection to 'wss://127.0.0.1:8443/wstest/ws/echoAsyncAnnotation' failed.
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket._connect(GrizzlyClientSocket.java:398)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.access[=14=]0(GrizzlyClientSocket.java:103)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.call(GrizzlyClientSocket.java:235)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.call(GrizzlyClientSocket.java:231)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.connect(GrizzlyClientSocket.java:249)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.openClientSocket(GrizzlyClientContainer.java:95)
at org.glassfish.tyrus.client.ClientManager.run(ClientManager.java:663)
at org.glassfish.tyrus.client.ClientManager.run(ClientManager.java:712)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:866)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:110)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:511)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:355)
at nl.fw.wsclienttest.WsClient.echoDemo(WsClient.java:69)
at nl.fw.wsclienttest.WsClient.main(WsClient.java:41)
以及我使用的完全不安全的测试客户端的代码:
import java.io.IOException;
import java.net.URI;
import java.security.KeyStore;
import java.security.cert.*;
import java.util.concurrent.*;
import javax.net.ssl.*;
import javax.websocket.*;
import org.glassfish.tyrus.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
public class WsClient {
static {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
private static final Logger log = LoggerFactory.getLogger(WsClient.class);
public static void main(String[] args) {
System.getProperties().put("javax.net.debug", "ssl,handshake,data,sslctx");
try {
new WsClient().echoDemo();
log.info("done");
} catch (Exception e) {
e.printStackTrace();
}
}
// localhost does not work via squid proxy
String destUri = "wss://127.0.0.1:8443/wstest/ws/echoAsyncAnnotation";
String proxyUri = "http://localhost:3128";
volatile Session wsSession = null;
void echoDemo() throws Exception {
final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
ClientManager client = ClientManager.createClient();
client.getProperties().put(ClientProperties.PROXY_URI, proxyUri);
client.getProperties().put(ClientProperties.SHARED_CONTAINER, false);
SSLContext sslCtx = createAllTrustingContext();
SslEngineConfigurator sslEngineConfigurator = new SslEngineConfigurator(sslCtx, true, false, false);
sslEngineConfigurator.setHostVerificationEnabled(false); //skip host verification
client.getProperties().put(ClientProperties.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator);
// time-out is set to 30 seconds for all operations, so handshake timeout does not work ...
// see org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.CLIENT_SOCKET_TIMEOUT
client.getProperties().put(ClientProperties.HANDSHAKE_TIMEOUT, 3000);
final CountDownLatch messageLatch = new CountDownLatch(1);
client.connectToServer(new Endpoint() {
@Override
public void onOpen(final Session session, EndpointConfig config) {
try {
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
log.info("Received message: {}", message);
wsSession = session;
messageLatch.countDown();
}
});
session.getBasicRemote().sendText("Hello world");
} catch (IOException e) {
e.printStackTrace();
}
}
}, cec, new URI(destUri));
try {
messageLatch.await(5, TimeUnit.SECONDS);
if (wsSession != null) {
wsSession.close();
}
} finally {
client.shutdown();
}
}
public static SSLContext createAllTrustingContext() throws Exception {
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init((KeyStore) null, "changeit".toCharArray());
ctx.init(kmf.getKeyManagers(), new TrustManager[] { new TrustServerCertAlways() }, null);
return ctx;
}
static class TrustServerCertAlways implements X509TrustManager {
@Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
log.debug("Trusting all client certificates.");
}
@Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
log.debug("Trusting all server certificates.");
}
@Override public X509Certificate[] getAcceptedIssuers() {
log.debug("No accepted issuers.");
return null;
}
}
}
这是使用 Java 8、squid 3.1.2 和 tyrus-standalone-client-1.12.jar
实现 websocket。
更新:
它仍然不适用于 Tyrus。但是,问题似乎不在于 squid,因为当我使 Chrome 使用代理并在此处连接到 SO 时,到 wss://qa.whosebug.com
的连接通过 squid 代理并且工作正常。
我正在使用 javax.websocket client simple example 的已接受答案中给出的测试程序来尝试获取 squid 代理 运行。
但是,我已将其更改为使用 websockets.org 回显服务器,因此 URI 已从 wss://real.okcoin.cn:10440/websocket/okcoinapi
更改为 wss://echo.websocket.org
。
当我不使用代理时,测试程序在 wss://echo.websocket.org
和 ws://echo.websocket.org
上工作正常。
当我通过 -Dhttp.proxyHost
、-Dhttp.proxyPort
、-Dhttps.proxyHost
和 -Dhttps.proxyPort
指定 JVM 范围的代理时,ws://
URI 工作正常,但 wss://
一个没有。
我已经验证(使用 tcpdump)流量正在流向代理,测试程序正在向代理发送 CONNECT
,并且代理发回 Connection established
。但是,那时没有其他事情发生:
# tcpdump -n -l -s 0 -S -X 'host 172.16.99.15'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
17:21:45.361023 IP 172.16.99.21.36521 > 172.16.99.15.3128: S 1720321489:1720321489(0) win 14600 <mss 1460,sackOK,timestamp 1135431 0,nop,wscale 5>
0x0000: 4500 003c 5696 4000 4006 c5e0 ac10 6315 E..<V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 05d1 0000 0000 ..c....8f.......
0x0020: a002 3908 1e74 0000 0204 05b4 0402 080a ..9..t..........
0x0030: 0011 5347 0000 0000 0103 0305 ..SG........
17:21:45.361763 IP 172.16.99.15.3128 > 172.16.99.21.36521: S 1626710395:1626710395(0) ack 1720321490 win 14480 <mss 1460,sackOK,timestamp 1127109 1135431,nop,wscale 7>
0x0000: 4500 003c 0000 4000 4006 1c77 ac10 630f E..<..@.@..w..c.
0x0010: ac10 6315 0c38 8ea9 60f5 a17b 668a 05d2 ..c..8..`..{f...
0x0020: a012 3890 613d 0000 0204 05b4 0402 080a ..8.a=..........
0x0030: 0011 32c5 0011 5347 0103 0307 ..2...SG....
17:21:45.361789 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710396 win 457 <nop,nop,timestamp 1135431 1127109>
0x0000: 4500 0034 5697 4000 4006 c5e7 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 05d2 60f5 a17c ..c....8f...`..|
0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 5347 .....l........SG
0x0030: 0011 32c5 ..2.
17:21:45.407930 IP 172.16.99.21.36521 > 172.16.99.15.3128: P 1720321490:1720321613(123) ack 1626710396 win 457 <nop,nop,timestamp 1135442 1127109>
0x0000: 4500 00af 5698 4000 4006 c56b ac10 6315 E...V.@.@..k..c.
0x0010: ac10 630f 8ea9 0c38 668a 05d2 60f5 a17c ..c....8f...`..|
0x0020: 8018 01c9 1ee7 0000 0101 080a 0011 5352 ..............SR
0x0030: 0011 32c5 434f 4e4e 4543 5420 6563 686f ..2.CONNECT.echo
0x0040: 2e77 6562 736f 636b 6574 2e6f 7267 3a34 .websocket.org:4
0x0050: 3433 2048 5454 502f 312e 310d 0a48 6f73 43.HTTP/1.1..Hos
0x0060: 743a 2065 6368 6f2e 7765 6273 6f63 6b65 t:.echo.websocke
0x0070: 742e 6f72 670d 0a50 726f 7879 2d43 6f6e t.org..Proxy-Con
0x0080: 6e65 6374 696f 6e3a 206b 6565 702d 616c nection:.keep-al
0x0090: 6976 650d 0a43 6f6e 6e65 6374 696f 6e3a ive..Connection:
0x00a0: 206b 6565 702d 616c 6976 650d 0a0d 0a .keep-alive....
17:21:45.408347 IP 172.16.99.15.3128 > 172.16.99.21.36521: . ack 1720321613 win 114 <nop,nop,timestamp 1127121 1135442>
0x0000: 4500 0034 93b9 4000 4006 88c5 ac10 630f E..4..@.@.....c.
0x0010: ac10 6315 0c38 8ea9 60f5 a17c 668a 064d ..c..8..`..|f..M
0x0020: 8010 0072 c795 0000 0101 080a 0011 32d1 ...r..........2.
0x0030: 0011 5352 ..SR
17:21:45.423007 IP 172.16.99.15.3128 > 172.16.99.21.36521: P 1626710396:1626710435(39) ack 1720321613 win 114 <nop,nop,timestamp 1127124 1135442>
0x0000: 4500 005b 93ba 4000 4006 889d ac10 630f E..[..@.@.....c.
0x0010: ac10 6315 0c38 8ea9 60f5 a17c 668a 064d ..c..8..`..|f..M
0x0020: 8018 0072 bdab 0000 0101 080a 0011 32d4 ...r..........2.
0x0030: 0011 5352 4854 5450 2f31 2e30 2032 3030 ..SRHTTP/1.0.200
0x0040: 2043 6f6e 6e65 6374 696f 6e20 6573 7461 .Connection.esta
0x0050: 626c 6973 6865 640d 0a0d 0a blished....
17:21:45.423041 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710435 win 457 <nop,nop,timestamp 1135446 1127124>
0x0000: 4500 0034 5699 4000 4006 c5e5 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 064d 60f5 a1a3 ..c....8f..M`...
0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 5356 .....l........SV
0x0030: 0011 32d4 ..2.
17:22:15.649132 IP 172.16.99.21.36521 > 172.16.99.15.3128: F 1720321613:1720321613(0) ack 1626710435 win 457 <nop,nop,timestamp 1143003 1127124>
0x0000: 4500 0034 569a 4000 4006 c5e4 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 064d 60f5 a1a3 ..c....8f..M`...
0x0020: 8011 01c9 1e6c 0000 0101 080a 0011 70db .....l........p.
0x0030: 0011 32d4 ..2.
17:22:15.650241 IP 172.16.99.15.3128 > 172.16.99.21.36521: F 1626710435:1626710435(0) ack 1720321614 win 114 <nop,nop,timestamp 1134681 1143003>
0x0000: 4500 0034 93bb 4000 4006 88c3 ac10 630f E..4..@.@.....c.
0x0010: ac10 6315 0c38 8ea9 60f5 a1a3 668a 064e ..c..8..`...f..N
0x0020: 8011 0072 8c5b 0000 0101 080a 0011 5059 ...r.[........PY
0x0030: 0011 70db ..p.
17:22:15.650255 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710436 win 457 <nop,nop,timestamp 1143003 1134681>
0x0000: 4500 0034 569b 4000 4006 c5e3 ac10 6315 E..4V.@.@.....c.
0x0010: ac10 630f 8ea9 0c38 668a 064e 60f5 a1a4 ..c....8f..N`...
0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 70db .....l........p.
0x0030: 0011 5059 ..PY
并不是代理在 Java TLS 连接方面存在问题。如果我改为(仍然使用 Java 8)通过代理建立普通 HTTPS 连接(比如 https://www.google.com
),我会看到客户端发送相同的 CONNECT
和相同的 Connection established
被代理发回,但随后 TLS 握手等正常进行并且 request/response 正常完成。
坦率地说,我对正在发生的事情(或者更确切地说没有发生的事情)感到困惑。
我能够 100% 重现问题中描述的问题。我使用 Squid 版本 3.5.17 (Windows 10 64bit),
本地 Tomcat 使用带有 "echo" 网络套接字和 Java 7 的自签名证书(但我认为 Java 8 没有任何区别)。
当我使用 org.glassfish.tyrus.bundles:tyrus-standalone-client:1.11
而不是 1.12
时一切正常。
当我发现这个错误修复时,我决定使用以前的版本:
2015/Nov/13:Grizzly 传输无法通过 HTTP 代理打开 wss 连接
(github-commit).
1.11 版于 2015 年 6 月发布,1.12 版于 2015 年 9 月发布,我希望在 1.13 版中修复 (另见 pom history)。
供参考,1.12 的输出(硬编码超时为 30 秒
在 org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.CLIENT_SOCKET_TIMEOUT
中,因此您必须等待一段时间才能出现错误)。
05:07:25.514 [Grizzly(1) SelectorRunner] TRACE o.g.t.c.g.c.GrizzlyClientFilter - handleConnect Using SSLEngineImpl. Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false 05:07:25.651 [Grizzly(1)] DEBUG o.g.t.c.g.c.GrizzlyClientFilter - handleRead websocket: null content-size=0 headers= HttpResponsePacket ( status=200 reason=Connection established protocol=HTTP/1.1 content-length=-1 committed=false headers=[] ) javax.websocket.DeploymentException: Connection to 'wss://127.0.0.1:8443/wstest/ws/echoAsyncAnnotation' failed. at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket._connect(GrizzlyClientSocket.java:398) at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.access[=14=]0(GrizzlyClientSocket.java:103) at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.call(GrizzlyClientSocket.java:235) at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.call(GrizzlyClientSocket.java:231) at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.connect(GrizzlyClientSocket.java:249) at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.openClientSocket(GrizzlyClientContainer.java:95) at org.glassfish.tyrus.client.ClientManager.run(ClientManager.java:663) at org.glassfish.tyrus.client.ClientManager.run(ClientManager.java:712) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:866) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:110) at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:511) at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:355) at nl.fw.wsclienttest.WsClient.echoDemo(WsClient.java:69) at nl.fw.wsclienttest.WsClient.main(WsClient.java:41)
以及我使用的完全不安全的测试客户端的代码:
import java.io.IOException;
import java.net.URI;
import java.security.KeyStore;
import java.security.cert.*;
import java.util.concurrent.*;
import javax.net.ssl.*;
import javax.websocket.*;
import org.glassfish.tyrus.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
public class WsClient {
static {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
private static final Logger log = LoggerFactory.getLogger(WsClient.class);
public static void main(String[] args) {
System.getProperties().put("javax.net.debug", "ssl,handshake,data,sslctx");
try {
new WsClient().echoDemo();
log.info("done");
} catch (Exception e) {
e.printStackTrace();
}
}
// localhost does not work via squid proxy
String destUri = "wss://127.0.0.1:8443/wstest/ws/echoAsyncAnnotation";
String proxyUri = "http://localhost:3128";
volatile Session wsSession = null;
void echoDemo() throws Exception {
final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
ClientManager client = ClientManager.createClient();
client.getProperties().put(ClientProperties.PROXY_URI, proxyUri);
client.getProperties().put(ClientProperties.SHARED_CONTAINER, false);
SSLContext sslCtx = createAllTrustingContext();
SslEngineConfigurator sslEngineConfigurator = new SslEngineConfigurator(sslCtx, true, false, false);
sslEngineConfigurator.setHostVerificationEnabled(false); //skip host verification
client.getProperties().put(ClientProperties.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator);
// time-out is set to 30 seconds for all operations, so handshake timeout does not work ...
// see org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.CLIENT_SOCKET_TIMEOUT
client.getProperties().put(ClientProperties.HANDSHAKE_TIMEOUT, 3000);
final CountDownLatch messageLatch = new CountDownLatch(1);
client.connectToServer(new Endpoint() {
@Override
public void onOpen(final Session session, EndpointConfig config) {
try {
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
log.info("Received message: {}", message);
wsSession = session;
messageLatch.countDown();
}
});
session.getBasicRemote().sendText("Hello world");
} catch (IOException e) {
e.printStackTrace();
}
}
}, cec, new URI(destUri));
try {
messageLatch.await(5, TimeUnit.SECONDS);
if (wsSession != null) {
wsSession.close();
}
} finally {
client.shutdown();
}
}
public static SSLContext createAllTrustingContext() throws Exception {
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init((KeyStore) null, "changeit".toCharArray());
ctx.init(kmf.getKeyManagers(), new TrustManager[] { new TrustServerCertAlways() }, null);
return ctx;
}
static class TrustServerCertAlways implements X509TrustManager {
@Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
log.debug("Trusting all client certificates.");
}
@Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
log.debug("Trusting all server certificates.");
}
@Override public X509Certificate[] getAcceptedIssuers() {
log.debug("No accepted issuers.");
return null;
}
}
}