WebSocket Secure java.nio.channels.UnresolvedAddressExceptio



我在使用WebSocket Secure时遇到了这个问题。我使用这个websocket库:'org.java-websocket:Java-WebSocket:1.3.0'。这个问题只出现在联想的智能手机上(不是所有型号的手机都有问题,比如联想A6000就能正常工作)。例如,在联想Vibe设备上发生错误。我在Nexus 4、Nexus 5、Nexus 5x、Nexus 6、Nexus 6P、联想A6000、联想Vibe、三星Galaxy SIII (CyanogenMod Android 4.4.4)上进行了测试。此列表中只有联想Vibe设备出现错误。下面是一个错误:

java.nio.channels.UnresolvedAddressException
下面是我的代码:
    final String url =  wss://*****.com/wss;
    URI uri=null;
    try{
        uri = new URI(url);
    }
    catch (Exception e)
    {
    }
    Map<String, String> headers = new HashMap<>();
    headers.put("auth_key", TOKEN);
    mWebSocketClient = new WebSocketClient(uri, new Draft_10(), headers, 0) {
        @Override
        public void onOpen(ServerHandshake handshakedata) {
        }
        @Override
        public void onMessage(String message) {
        }
        @Override
        public void onClose(int code, String reason, boolean remote) {
        }
        @Override
        public void onError(Exception ex) {
            //HERE I HANDLE AN ERROR ON LENOVO VIBE
        }
    };
    try{
        SSLContext sslContext = SSLContext.getDefault();
        mWebSocketClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
        mWebSocketClient.connect();
    }catch (Exception e)
    {
    }

错误发生在库中,在WebSocketClient.java类中:

private final void interruptableRun() {
    if( channel == null ) {
        return;// channel will be initialized in the constructor and only be null if no socket channel could be created or if blocking mode could be established
    }
    try {
        String host;
        int port ;
        if( proxyAddress != null ) {
            host = proxyAddress.getHostName();
            port = proxyAddress.getPort();
        } else {
            host = uri.getHost();
            port = getPort();
        }
        channel.connect( new InetSocketAddress( host, port ) );
        conn.channel = wrappedchannel = createProxyChannel( wsfactory.wrapChannel( channel, null, host, port ) );
        timeout = 0; // since connect is over
        sendHandshake();
        readthread = new Thread( new WebsocketWriteThread() );
        readthread.start();
    } catch ( ClosedByInterruptException e ) {
        onWebsocketError( null, e );
        return;
    } catch ( /*IOException | SecurityException | UnresolvedAddressException*/Exception e ) {//
        onWebsocketError( conn, e );
        conn.closeConnection( CloseFrame.NEVER_CONNECTED, e.getMessage() );
        return;
    }
    ByteBuffer buff = ByteBuffer.allocate( WebSocketImpl.RCVBUF );
    try/*IO*/{
        while ( channel.isOpen() ) {
            if( SocketChannelIOHelper.read( buff, this.conn, wrappedchannel ) ) {
                conn.decode( buff );
            } else {
                conn.eot();
            }
            if( wrappedchannel instanceof WrappedByteChannel ) {
                WrappedByteChannel w = (WrappedByteChannel) wrappedchannel;
                if( w.isNeedRead() ) {
                    while ( SocketChannelIOHelper.readMore( buff, conn, w ) ) {
                        conn.decode( buff );
                    }
                    conn.decode( buff );
                }
            }
        }
    } catch ( CancelledKeyException e ) {
        conn.eot();
    } catch ( IOException e ) {
        conn.eot();
    } catch ( RuntimeException e ) {
        // this catch case covers internal errors only and indicates a bug in this websocket implementation
        onError( e );
        conn.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
    }
}

On This Line:

channel.connect( new InetSocketAddress( host, port ) );

另外,如果你知道任何其他WebSocket库可以在所有设备上正常工作,在那里我可以使用wss链接并放置自定义头,请分享。

最后我找到了一个解决办法。这里是:

1)从库中重写WebSocketClient.java类(或者只是提取库并将其粘贴到项目中)

2)创建新类:
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class MyInetSocketAddress {
    public static InetSocketAddress myInetSocketAddress(String hostname, int port, boolean needResolved) 
    {
        if (hostname == null || port < 0 || port > 65535) {
            throw new IllegalArgumentException("host=" + hostname + ", port=" + port);
        }
        InetAddress addr = null;
        if (needResolved) {
            try {
                addr = InetAddress.getByName(hostname);
            } 
            catch (Exception ignored) 
            {
            }
        }
        return new InetSocketAddress(addr, port);
    }
}
3)打开WebSocketClient.java类,找到:

interruptableRun ()

方法并替换为:

频道。

连接InetSocketAddress(主机,端口);

和这个:

频道。连接(MyInetSocketAddress。myInetSocketAddress(host, port, true));

4)还在方法的末尾添加try/catch - replace:

。closeConnection (CloseFrame。

异常关闭,e.t getmessage ());

:

try{
    conn.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
}
catch (Exception e1)
{
}
private class WebsocketWriteThread implements Runnable {
    @Override
    public void run() {
        Thread.currentThread().setName( "WebsocketWriteThread" );
        try {
            while ( !Thread.interrupted() ) {
                SocketChannelIOHelper.writeBlocking( conn, wrappedchannel );
            }
        } catch ( IOException e ) {
            conn.eot();
        } catch ( InterruptedException e ) {
            // this thread is regularly terminated via an interrupt
        }
    }
}

如下所示:

private class WebsocketWriteThread implements Runnable {
    @Override
    public void run() {
        Thread.currentThread().setName( "WebsocketWriteThread" );
        try {
            while ( !Thread.interrupted() ) {
                SocketChannelIOHelper.writeBlocking( conn, wrappedchannel );
            }
        } catch ( IOException e ) {
            conn.eot();
        } catch ( InterruptedException e ) {
            // this thread is regularly terminated via an interrupt
        } catch (Exception e)
        {
        }
    }
}
另外,不要忘记使用这个:
ProviderInstaller.installIfNeeded(getApplicationContext());
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
mWebSocketClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
mWebSocketClient.connect();

如上所示。

希望这对其他人有帮助!))如果你有任何问题-问我

相关内容

  • 没有找到相关文章

最新更新