java - WebSocket 客户端关闭连接
问题描述
我正在尝试用 Java 构建一个独立的 WebSocket 客户端,该客户端连接到 C# 中的 WebSocket 服务器。我正在使用为 WebSocket 服务器生成的自签名证书。我可以使用 WSS 在 Chrome 浏览器中连接到 WebSocket 服务器,没有任何问题。尝试使用TooTallNate/Java-WebSocket库时,它不起作用。OnClose 方法在连接时立即调用。
我在生成的 *.pfx 文件中有一个自签名证书,用于 C# 服务器并导入到我的受信任的根存储中。我使用 keytool 从这个文件创建了一个 *.jks (我认为我已经正确地做到了)。我正在使用由 keytool 在我的代码中生成的 keystore.jks。
这是我的主要方法:
public static void main(String[] args) throws Exception {
ChatClient chatclient = new ChatClient("wss://thomas.localnetwork.com:65120/wsserver?userId=Thomas", "Thomas", "1", "1", "L");
// load up the key store
String STORETYPE = "JKS";
String KEYSTORE = "C:\\Users\\thomas\\Desktop\\keystore.jks";
String STOREPASSWORD = "test12345";
String KEYPASSWORD = "test";
KeyStore ks = KeyStore.getInstance( STORETYPE );
File kf = new File( KEYSTORE );
ks.load( new FileInputStream( kf ), STOREPASSWORD.toCharArray() );
KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
kmf.init( ks, KEYPASSWORD.toCharArray() );
TrustManagerFactory tmf = TrustManagerFactory.getInstance( "SunX509" );
tmf.init( ks );
SSLContext sslContext = null;
sslContext = SSLContext.getInstance( "TLS" );
sslContext.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null );
// sslContext.init( null, null, null ); // will use java's default key and trust store which is sufficient unless you deal with self-signed certificates
SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault();
chatclient.setSocketFactory( factory );
chatclient.connectBlocking();
BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
while ( true ) {
String line = reader.readLine();
if( line.equals( "close" ) ) {
chatclient.closeBlocking();
} else if ( line.equals( "open" ) ) {
chatclient.reconnect();
} else {
ucm.send( line );
}
}
}
这是我收到的例外情况:
Closed connection on wss://laptop-thomas.compuflex1.com:65120/wsucm_deviceagent?userId=Thomas
javax.net.ssl.SSLException: java.net.SocketException: Connection reset
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1906)
at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1870)
at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1815)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:116)
at java.io.InputStream.read(InputStream.java:101)
at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:424)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:210)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.read(InputRecord.java:503)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
... 3 more
有什么方法可以让我获得有关握手的更多详细信息或实际问题是什么?异常堆栈跟踪似乎根本没有帮助。
解决方案
我的问题是我的本地防火墙引起了问题。我还发现我可以将证书安装到 Java 的受信任根存储中。
请注意,每个 Java 版本(JDK 和 JRE)都有自己的“cacerts”文件。请务必为您的开发或运行时环境安装正确的版本。我把头撞在墙上,因为在我意识到这一点之前它在 IntelliJ 中不起作用。
- 将证书安装到 JVM 受信任的根存储
- 检查是否安装正确
- 删除代码的密钥库部分
这是将证书安装到正确位置后对我的代码的更改。
public static void main(String[] args) throws Exception {
ChatClient chatclient = new ChatClient("wss://thomas.localnetwork.com:65120/wsserver?userId=Thomas", "Thomas", "1", "1", "L");
chatclient.connectBlocking();
BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
while ( true ) {
String line = reader.readLine();
if( line.equals( "close" ) ) {
chatclient.closeBlocking();
} else if ( line.equals( "open" ) ) {
chatclient.reconnect();
} else {
chatclient.send( line );
}
}
}
推荐阅读
- c++ - 如何使用 Visual Studio 2019 设置 sqlite
- c++ - 将 void 指针分配给另一个 void 指针
- r - 基于行和列和的 0 和 1 条件随机矩阵
- python - python中一个3D图形中的多个2D等高线图
- sql - 使用时按日期分组以防万一
- security - IPV6 和 MAC 地址
- python - 如何根据列从另一个数据集中复制粘贴值
- javascript - Ajax 错误 403 通过在实时版本上发送数据 var base64,而不是本地
- html - 电子邮件和密码。如果正确,请转到 url
- linux - 从编译库的反汇编中仅获取十六进制字节值