Rahim Rahimov Rahim Rahimov - 27 days ago 20
Java Question

WebSocket Secure java.nio.channels.UnresolvedAddressException

I faced with the problem using WebSocket Secure. I using this websocket library: 'org.java-websocket:Java-WebSocket:1.3.0'. The problem appears only on LENOVO smartphones (not at all models, for example Lenovo A6000 works as expected). For example error occurs on Lenovo Vibe devices. I tested it on Nexus 4, Nexus 5, Nexus 5x, Nexus 6, Nexus 6P, Lenovo A6000, Lenovo Vibe, Samsung Galaxy SIII (CyanogenMod Android 4.4.4). Error appeared only on Lenovo Vibe devices from this list.
Here is an error:

java.nio.channels.UnresolvedAddressException


Here is my code:

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)
{
}


Error occurs inside the library, here:

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 ) );


Also, if you know any other WebSocket library that properly working on all devices, where i can use wss links and put custom headers, please share.

Answer

Finally i found a solution.. and here it is:

1) Rewrite WebSocketClient.java class from the libraty (or just extract the library and paste it to your project)

2) Create new class:

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) Open your WebSocketClient.java class, find:

interruptableRun()

method and replace this:

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

with this one:

channel.connect( MyInetSocketAddress.myInetSocketAddress(host, port, true) );

4) Also add try/catch at the end of the method - replace:

conn.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );

with:

try{
    conn.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
}
catch (Exception e1)
{
}

5) As additional add catch(Exception e) here:

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
        }
    }
}

like shown here:

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)
        {
        }

    }
}

6) Also, don't forget to use this:

SSLContext sslContext = SSLContext.getDefault();
mWebSocketClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
mWebSocketClient.connect();

as shown above in my question.

Hope this will help others!)) if you have any questions - ask me)

Comments