Giter Club home page Giter Club logo

nv-websocket-client's Issues

Add method to clear out all listeners

It is only possible to add listeners into the socket, but not remove them. This may cause some problems with lifecycle-bound interactions, i.e. Android activities and fragments. Listeners need to be closed/cleaned at some point that's not internally or on a disconnection.

Please provide a manual clearAllListeners() method to do so.

WebSocketFactory.setSSLContext() and WebSocketFactory.setSSLSocketFactory() should not allow both to be set.

Thanks, I've gotten this library to work on KitKat and Lollipop in my app. Much much easier to use than AndroidAsync!!!

Here's is a suggestion for improving your API.

I made the mistake of calling both WebSocketFactory.setSSLContext() and WebSocketFactory.setSSLSocketFactory() when I wanted it to use my own SSLSocketFactory. It turned out that if I pass the context, it will never use the factory instance I gave it.

You should either not allow the above, or when SocketFactorySettings.selectSocketFactory() is called, use the factory instance that was provided if not null first, else use an instance from the SSLContext.

Custom ping message in pingSender

I would like to be able to change the standard ping message to be the current date instead of count, this would make it easier to calculate the round-trip-time latency to the server. Is it possible to override the default implementation?

Open source license?

I apologize in advance if I missed it somewhere but under what open source license is this library being distributed? Apache 2? GPL? Something else?

Error 1002

Hello
Im trying to get an open socket to receive information every X, but the conection is closed after a little time. This is the line I get at disconnect:

WebSocketFrame(FIN=1,RSV1=0,RSV2=0,RSV3=0,Opcode=CLOSE,Length=84,CloseCode=1002,Reason="At least one of the reserved bits of a frame is set: RSV1=true,RSV2=true,RSV3=true")

Im already using setExtended(true) but it doesn't work.

Reconnect Socket

I have been going through the code looking for a way to reconnect a socket with no luck. I tried to simply run .connect() again on an interval until the connection went through, but I had no luck. It will just keep throwing a WebSocketExpection everytime I try to use .connect(). This is what I tried:

@Override
public void onDisconnected(WebSocket socket, WebSocketFrame serverCloseFrame,
                           WebSocketFrame clientCloseFrame, boolean closedByServer) {
    if (!closedByServer) {
        RSMCPlugin.Instance.getLogger().warning("Socket disconnected. Will try every 3 seconds until successful");
        this.tryReconnect(socket);
    }
}

private void tryReconnect(WebSocket socket) {
    try {
        Thread.sleep(3000);
        socket.connect();
    }
    catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    catch (WebSocketException e) {
        this.tryReconnect(socket);
    }
}

I am using version 1.5 from Maven.

Is this a bug? Is not, can you please update the documentation to show the proper way to attempt reconnecting.

Also, you library is the only one I have been able to find that works on my WSS server. I am not sure why, but great job!

WebSocketAdapter.onError() vs WebSocketAdapter.onDisconnected()

Seems like onError() can be invoked multiple times for many different things. I triggered this three times when I turned off Wifi on my Android device. onDisconnected() was triggered once.

Belows were from onError():

com.neovisionaries.ws.client.WebSocketException: An I/O error occurred while a frame was being read from the web socket.
com.neovisionaries.ws.client.WebSocketException: Flushing frames to the server failed
com.neovisionaries.ws.client.WebSocketException: Flushing frames to the server failed

If I just wanted to be callback whenever I need to re-initiate the websocket connection, regardless of the error, which callback should I register for?

Seems like onDisconnected() is all I need?

Move notifyFinished to finally block in ReadingThread

We had a lot of leaked sockets in CLOSE_WAIT state and a lot of active leaked PingTimers threads.

After some digging I's able to reproduce the scenario which causes a leak. The main reason of this is fixed in #23 when you add a check before send https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/WebSocket.java#L2213 We upgraded the version and everything works fine.

In general we had the following scenario:

  1. TCP FIN packet come.
  2. https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/ReadingThread.java#L306 this call fires WebSocketException
  3. This exception passed to user's callback here https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/ReadingThread.java#L345
  4. User call disconnect in onError callback to make sure that socket is closed
  5. disconnect call sets null to mReadingThread and mWritingThread
  6. ReadingThread tries to send close frame https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/ReadingThread.java#L352
  7. sendFrame throws NullPointerException because mWritingThread is null
  8. notifyFinished is not called and WebSocket.finish isn't called too too https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/ReadingThread.java#L114 Pinger handles link to WebSocket object and doesn't allow gc call finilize method. This was a reason of socket and PingerTimer leak

Why am I writing the ticket if everything is working fine in the new version? Good question!

As postmortem of my investigation, I'm really want to ask you to move notifyFinished call to finally block here https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/ReadingThread.java#L74 to make sure that ReadingThread calls onReadingThreadFinished in all cases to avoid such issues in future.

Thanks,

Closing a web socket while in the process of connecting

Hi, I've recently run into a problem where I need to close the web socket before it has finished connecting. Looking at the code in Websocket.disconnect() reveals this:

        switch (mStateManager.getState())
        {
            case CREATED:
                finishAsynchronously();
                return this;

            case OPEN:
                break;

            default:
                // - CONNECTING
                //     It won't happen unless the programmer dare call
                //     open() and disconnect() in parallel.
                //
                // - CLOSING
                //     A closing handshake has already been started.
                //
                // - CLOSED
                //     The connection has already been closed.
                return this;
        }

What I'm doing currently is to get the raw socket and call close() on it, which generally works, but sometimes doesn't. Waiting for the OPEN to occur is another option, but if the network is really slow, it's really not ideal for my purposes. Can we add some behavior to cancel the connection if it's in progress?

Congestion control

Do you have any plan to add congestion control to you library?

I was able to use TCP congestion control for the reading thread with current implementation by adding control logic to user's callbacks but have no idea how to add congestion control to writing thread. Right now I get OOM if i'm send more then could transfer to the server because all frames are stored in unlimited linked list before they are sent to server.

Socket is not closed when handshake is failed

We need to explicitly close the underlying socket when a handshake error happens. It could stay in ESTABLISHED or CLOSE_WAIT (depends on server implementation).

        try
        {
            // Perform WebSocket handshake.
            headers = shakeHands();
        }
        catch (WebSocketException e)
        {
            ( need to close underlying tcp Socket here)
            // Change the state to CLOSED.
            mStateManager.setState(CLOSED);

            // Notify the listener of the state change.
            mListenerManager.callOnStateChanged(CLOSED);

            // The handshake failed.
            throw e;
        }

SOCKS V5 Proxy instead of HTTP

It's just a question, not an issue. Is it possible to somehow use SOCKS V5 proxy instead oh HTTP one? I want to use Tor as proxy which provides SOCKS5 only proxy at 127.0.0.1:9050.

Add Websocket Compression using Permessage-Deflate

Hello,

Thanks for creating nv-websocket-client!

I have used your fantastic library to add SSL support to the Android-DDP client library by delight-im.

It would be fantastic if you could make nv-websocket-client support websocket compression using permessage deflate.

Meteor 1.2 recently introduced support for websocket compression using this method. Having support for this feature would greatly reduce the amount of data transferred over the connection.

Here is the official specification document: Compression Extensions for WebSocket

Initial connection timeout?

Is there currently the capability to set the initial connection timeout for the socket connection? I think this would use the socket method connect(SocketAddress endpoint, int timeout).

My code fragment looks like this, and for timeout_ms =6000, the timeout for the initial connection is highly variable, but can definitely be > 30 sec. The SO_TIMEOUT does not seem to have any effect on the initial connection timeout.

websocket = factory.createSocket(connectionURI);
Socket s = websocket.getSocket();
s.setSoTimeout(timeout_ms);
websocket.addListener(this);
websocket.connect();

Getting Error when included Library as an external jar to my Android App

Hi

I am getting following error if i add nv-websocket-client.1.21.jar as an external to my App.

ClassNotFoundException i got it.
Please suggest simplest way to fix it.

01-26 13:28:38.278: E/AndroidRuntime(18304): FATAL EXCEPTION: AsyncTask #3
01-26 13:28:38.278: E/AndroidRuntime(18304): Process: com.example.websock1, PID: 18304
01-26 13:28:38.278: E/AndroidRuntime(18304): java.lang.RuntimeException: An error occurred while executing doInBackground()
01-26 13:28:38.278: E/AndroidRuntime(18304): at android.os.AsyncTask$3.done(AsyncTask.java:309)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.util.concurrent.FutureTask.run(FutureTask.java:242)
01-26 13:28:38.278: E/AndroidRuntime(18304): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.lang.Thread.run(Thread.java:818)
01-26 13:28:38.278: E/AndroidRuntime(18304): Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/neovisionaries/ws/client/WebSocketFactory;
01-26 13:28:38.278: E/AndroidRuntime(18304): at com.example.websock1.MainActivity$WebSocketOperation.connectWebSocket(MainActivity.java:104)
01-26 13:28:38.278: E/AndroidRuntime(18304): at com.example.websock1.MainActivity$WebSocketOperation.doInBackground(MainActivity.java:75)
01-26 13:28:38.278: E/AndroidRuntime(18304): at com.example.websock1.MainActivity$WebSocketOperation.doInBackground(MainActivity.java:1)
01-26 13:28:38.278: E/AndroidRuntime(18304): at android.os.AsyncTask$2.call(AsyncTask.java:295)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
01-26 13:28:38.278: E/AndroidRuntime(18304): ... 4 more
01-26 13:28:38.278: E/AndroidRuntime(18304): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.neovisionaries.ws.client.WebSocketFactory" on path: DexPathList[[zip file "/data/app/com.example.websock1-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.websock1-1/lib/arm, /vendor/lib, /system/lib]]
01-26 13:28:38.278: E/AndroidRuntime(18304): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
01-26 13:28:38.278: E/AndroidRuntime(18304): ... 9 more
01-26 13:28:38.278: E/AndroidRuntime(18304): Suppressed: java.lang.ClassNotFoundException: com.neovisionaries.ws.client.WebSocketFactory
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.lang.Class.classForName(Native Method)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
01-26 13:28:38.278: E/AndroidRuntime(18304): at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
01-26 13:28:38.278: E/AndroidRuntime(18304): ... 10 more
01-26 13:28:38.278: E/AndroidRuntime(18304): Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
01-26 13:28:39.199: E/WindowManager(18304): android.view.WindowLeaked: Activity com.example.websock1.MainActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{8e405fd V.E...... R......D 0,0-1026,486} that was originally added here
01-26 13:28:39.199: E/WindowManager(18304): at android.view.ViewRootImpl.(ViewRootImpl.java:368)
01-26 13:28:39.199: E/WindowManager(18304): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)
01-26 13:28:39.199: E/WindowManager(18304): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
01-26 13:28:39.199: E/WindowManager(18304): at android.app.Dialog.show(Dialog.java:319)
01-26 13:28:39.199: E/WindowManager(18304): at com.example.websock1.MainActivity$WebSocketOperation.onPreExecute(MainActivity.java:70)
01-26 13:28:39.199: E/WindowManager(18304): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:604)
01-26 13:28:39.199: E/WindowManager(18304): at android.os.AsyncTask.execute(AsyncTask.java:551)
01-26 13:28:39.199: E/WindowManager(18304): at com.example.websock1.MainActivity$1.onClick(MainActivity.java:46)
01-26 13:28:39.199: E/WindowManager(18304): at android.view.View.performClick(View.java:5204)
01-26 13:28:39.199: E/WindowManager(18304): at android.view.View$PerformClick.run(View.java:21153)
01-26 13:28:39.199: E/WindowManager(18304): at android.os.Handler.handleCallback(Handler.java:739)
01-26 13:28:39.199: E/WindowManager(18304): at android.os.Handler.dispatchMessage(Handler.java:95)
01-26 13:28:39.199: E/WindowManager(18304): at android.os.Looper.loop(Looper.java:148)
01-26 13:28:39.199: E/WindowManager(18304): at android.app.ActivityThread.main(ActivityThread.java:5417)
01-26 13:28:39.199: E/WindowManager(18304): at java.lang.reflect.Method.invoke(Native Method)
01-26 13:28:39.199: E/WindowManager(18304): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
01-26 13:28:39.199: E/WindowManager(18304): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

onDisconnect/onError not called on Android emulators

I tested out this websocket on Android emulators, but found that the sockets were not getting closed when I turned off the wifi.

What I expected to happen was to instantly get one or more onError calls followed by a onDisconnect call, the moment I shut off the wifi. That is what happens on my physical device (Android 5.0 AKA API 21).

What actually happened was nothing. Nothing happened on further outgoing frames either, it was as if the server simply stopped responding.

I tested this out on Genymotion(v2.6.0) emulators running Android API versions 19, 21, 22 and 23, respectively. This is the code I used to open the websocket:

    final WebSocket webSocket = webSocketFactory.createSocket("wss://example.com/websocket");
    webSocket.addListener(new MyWebSocketAdapter());
    webSocket.setPongInterval(45000);
    webSocket.connect();

PS: I love the library, the efford is greatly appreciated. Aside from this issue it works quite well, is easy to set up and is very thoroughly documented. Thank you!

Thread.interrupt() doesn't unblock socket's InputStream.read()

Hi,

We are using the ping/pong functionality to check connectivity between a client and a server. If we don't receive pong responses from the server we are calling disconnect method.

disconnect method tries to interrupt ReadingThread which is blocked on read() operation. The main issue the socket's input stream has a platform specific behaviour when thread is interrupted. For example, it doesn't work on my Mac OS oracle jdk 1.6 & 1.8. ReadingThread is waiting on readFrame forever after disconnect. Apparently interrupt() approach doesn't work for unblocking socket I/O on "most" modern Java platforms stackoverflow. As I know only close() has note in javadoc about throwing SocketException in threads blocked in an I/O operation.

Right now I'm using webSocket.getSocket().close() after disconnect() method to explicitly unblock all I/O operation but it causes a lot of exception from websocket library.

It will be great to have more stable disconnect behaviour.

move creation of raw socket from WebSocketFactory class to WebSocket

hi, I implement a wrapper of your lib for Android.
The problem is next - in Android all networking should be in background threads, so even creation of WebSocket instance is problem, cause method WebSocketFactory.createSocket() direct calls method createRawSocket(...). This method call Socket.connect(...). Thats mean when I just create Websocket, rawsocket under it become already connected, even before I call Websocket.connect().

so my suggestion is next: move creation and connection of raw socket "createRawSocket(host, port, secure, timeout)" from WebSocketFactory to WebSocket.connect() method.

WebSocket is closing when device sleeps.

A few seconds after the screen goes off, the (https over gprs) websocket connection closes.

04-12 16:39:23.534  15149-15201/com.foo.bar D/NativeCrypto﹕ ssl=0x61bd9e98 info_callback where=0x4004 ret=256
04-12 16:39:23.534  15149-15201/com.foo.bar D/NativeCrypto﹕ ssl=0x61bd9e98 SSL3 alert read:W:CN warning close notify
04-12 16:39:23.534  15149-15201/com.foo.bar D/NativeCrypto﹕ ssl=0x61bd9e98 info_callback ignored
04-12 16:39:23.536  15149-15201/com.foo.bar E/CommsService﹕ error
    com.neovisionaries.ws.client.WebSocketException: The end of the stream has been reached unexpectedly.
            at com.neovisionaries.ws.client.WebSocketInputStream.readBytes(WebSocketInputStream.java:153)
            at com.neovisionaries.ws.client.WebSocketInputStream.readFrame(WebSocketInputStream.java:44)
            at com.neovisionaries.ws.client.ReadingThread.readFrame(ReadingThread.java:306)
            at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:93)
            at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

(The code then opens a new connection, and the futile cycle continues...)

How can I avoid this? I want the websocket to stay listening for packets from the server, while the phone sleeps.

(I have made "connection stays listening while device sleeps" work for a plain TCP connection before, but websocket connections are behaving differently.)

WebSocketFactory.createSocket causes an exception on Android

Here is the stack:

at java.net.InetAddress.lookupHostByName(InetAddress.java:431)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getByName(InetAddress.java:305)
at java.net.InetSocketAddress.(InetSocketAddress.java:100)
at java.net.InetSocketAddress.(InetSocketAddress.java:85)
at com.neovisionaries.ws.client.WebSocketFactory.createDirectRawSocket(WebSocketFactory.java:621)
at com.neovisionaries.ws.client.WebSocketFactory.createRawSocket(WebSocketFactory.java:577)
at com.neovisionaries.ws.client.WebSocketFactory.createSocket(WebSocketFactory.java:509)
at com.neovisionaries.ws.client.WebSocketFactory.createSocket(WebSocketFactory.java:488)

Specifically the WebSocketFactory.java:621: SocketAddress address = new InetSocketAddress(host, port); which causes a network call. It kind of defeats the purpose of having connectAsynchronously.

The fix seems to be easy. Instead of WebSocketFactory.java:621

    // The address to connect to.
    SocketAddress address = new InetSocketAddress(host, port);

    // Create an instance that will execute the task to connect to the server later.
    return new SocketConnector(socket, address, timeout);

do

    // Create an instance that will execute the task to connect to the server later.
    return new SocketConnector(socket, host, port, timeout);

Then have SocketConnector call new InetSocketAddress(host, port); on the first call to connect().

Reconnect

             public void onDisconnected...{

                    try {

                        // ws = ws.recreate().connect();
                        ws = ws.recreate().connectAsynchronously();                          

                    } catch (Exception e) {                         

                    }
             }

I've tried to reconnect the socket once server DOWN(Disconnect), But it's not reconnect the websocket when again server UP(Connected). I suppose to start manually, Websockets is not re-establish the connection. I'm try to implement this websocket for reconnect the websocket once Server is available. But this re-establishment make problem to connect again.

Fixed NPE if no websocket extensions in server response

NPE occurs if no SEC-WEBSOCKET-EXTENSIONS header in server response.
See patch below. I have no permission to create a pull request.

diff --git a/src/main/java/com/neovisionaries/ws/client/WebSocket.java b/src/main/java/com/neovisionaries/ws/client/WebSocket.java
index 5d6d485..3b295ac 100644
--- a/src/main/java/com/neovisionaries/ws/client/WebSocket.java
+++ b/src/main/java/com/neovisionaries/ws/client/WebSocket.java
@@ -3220,6 +3220,11 @@ public class WebSocket
      */
     private PerMessageCompressionExtension findAgreedPerMessageCompressionExtension()
     {
+        if (mAgreedExtensions == null)
+        {
+            return null;
+        }
+
         for (WebSocketExtension extension : mAgreedExtensions)
         {
             if (extension instanceof PerMessageCompressionExtension)

which method i can use if pc WIFI shutdown

Hi,

The following methods are not called after i close my pc wifi,which method i can use if pc WIFI shutdown

@OverRide
public void onCloseFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@OverRide
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
}
@OverRide
public void onMessageError(WebSocket websocket,WebSocketException cause, List frames) throws Exception {
}
@OverRide
public void onUnexpectedError(WebSocket websocket,WebSocketException cause) throws Exception {
}

@Override
public void onConnectError(WebSocket websocket, WebSocketException exception) throws Exception {
}

@Override
public void onFrameError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame){

}

@Override
public void onTextMessageError(WebSocket websocket, WebSocketException cause, byte[] data){

}


@Override
public void onSendError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame){

}
@Override
public void onStateChanged(WebSocket websocket, WebSocketState newState) throws Exception {

}

@Override
public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception{

}


@Override
public void onSendingHandshake(WebSocket websocket, String requestLine, List<String[]> headers) throws Exception{
}

Thanks.
coco.

Proper way of send error handling

Hello,

it's not clear for me how to handle send errors correctly. In my Service I create an AsyncTask, which handles ArrayBlockingQueue in a loop. Then I run connectAsynchronously() in this service. Into the mentioned queue I add messages I want to send. As far as I understand, sendText() returns even in case of an error - the onSendError() callback is then called, but all the code after sendText() invocation is executed. How can I then implement some way to buffer my data in a database in case of transmission problems? I tried to save the data in a database in onSendError() or onFrameUnsent() and clear the queue head in onFrameSent(), but it appears, that onFrameSent() is executed also after a ping frame, so I would probably have to check the queue head for the getPayloadText() of a sent frame. Am I right?

Cheers,
Matthew

can`t connect tlsv1.2

Hi , TakahikoKawasaki . Do you know how to connect tlsv1.2 server on android?I tried to connect SSLv3 and TLSv1 successfully。I have said that since API 9 ,some protocols were supported . Besides that , since API 16 , TLSV1.1 and TLSV1.2 are also supported on android . But I can not do it . I`m looking forward that to you can help me to solve it !
Here is my code:

public SSLContext getSSLContextOld(String imUrl) throws KeyStoreException,
        NoSuchAlgorithmException, CertificateException, IOException,
        KeyManagementException {
    KeyStore keyStore = KeyStore.getInstance("BKS");
    keyStore.load(getInputStream(imUrl), "000000".toCharArray());
    // TrustManager decides which certificate authorities to use.
    TrustManagerFactory trustManagerFactory = TrustManagerFactory
            .getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(keyStore);
    // Since API 9,the following protocols have been
    // supported:Default,SSL,SSLv3,TLS,TLSv1
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    Log.e(TAG, "protocol-->" + sslContext.getProtocol());
    sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
    return sslContext;
}

public void initWs(String imAddress, String encoderToken)
        throws IOException, WebSocketException, URISyntaxException,
        NoSuchAlgorithmException, KeyStoreException, CertificateException,
        KeyManagementException, UnrecoverableKeyException {
    // "wss://domain:port/im"
    String imUrl = imAddress + "?token=" + encoderToken;
    WebSocketFactory webSocketFactory = new WebSocketFactory();
    SSLContext sslContext = getSSLContextOld(imUrl);
    // webSocketFactory.setSSLContext(sslContext);// method 1
    SSLSocketFactory factory = (SSLSocketFactory) sslContext
            .getSocketFactory();//method 2
    webSocketFactory.setSSLSocketFactory(factory);
    webSocket = webSocketFactory
            .setConnectionTimeout(WEBSOCKET_CONNECT_TIME_OUT)
            .createSocket(imUrl).setPingInterval(PING_PONG_INTERVAL)
            // .setPongInterval(PING_PONG_INTERVAL)
            .addListener(webSocketAdapter);
    webSocket.connect();

}

android integration

These seems like its not creating a connection when implemented on android.......

App does not know if the frame was queued or not.

Hi,

is there a way, how to know whether the frame was stored into queue or it was ignored? From source code it does not seem like there is a way. But I might be wrong. So is there some recommended way how to deal with this?

Thanks!

Socket is getting disconnected if there is case of empty frame

I got an issue and debugged it "socket was getting disconnected due to the fact the library is trying to read incoming frame which might not have any bytes available".

Easy proposed solution: Following lines

if (count <= 0)
{
// The end of the stream has been reached unexpectedly.
throw new WebSocketException(WebSocketError.INSUFFICENT_DATA,"The end of the stream has been reached unexpectedly.");
}

in WebSocketInputStream.java with in readBytes() method at line 141 should be commented out.

A question

There was WebSocketException buy I don't know who's fault it is either the android side or the server side.

W/System.err: com.neovisionaries.ws.client.WebSocketException: The status line of the opening handshake response is empty.
W/System.err: at com.neovisionaries.ws.client.HandshakeReader.readStatusLine(HandshakeReader.java:99)
W/System.err: at com.neovisionaries.ws.client.HandshakeReader.readHandshake(HandshakeReader.java:48)
W/System.err: at com.neovisionaries.ws.client.WebSocket.readHandshake(WebSocket.java:2857)
W/System.err: at com.neovisionaries.ws.client.WebSocket.shakeHands(WebSocket.java:2736)
W/System.err: at com.neovisionaries.ws.client.WebSocket.connect(WebSocket.java:1865)

Failed to get the input stream of the raw socket

Hey there. This library looks pretty solid. I'm porting from CodeButler android-websockets as it hasn't been updated in a few years and doesn't follow the spec correctly.

Everything seems pretty straightforward to setup but I am always getting this error with the same URL that works on the other library:

"Failed to get the input stream of the raw socket"

I receive a
state changed: connecting
state changed: closed
onError() - Failed to get the input stream of the raw socket

I'm just wondering if you have any insight or more information about what could be causing this error. Thanks

[Question] Set a ping timetout ?

I would like to handle state where websocket is connected but no data received (eg : you're in subway, your device is connected to 3G but no data received and you cannot send frames).

Is it possible to set a ping timeout ?

onDisconnected not called all the time ?

When I disconnect the websocket manually by

websocket.disconnect()

the onDisconnected event is not called, only the onStateChanged event is called.

I tried to debug a little bit and here is what I see

  • There is a call to WebSocket.stopThreads() followed by ReadingThread.requestStop() that should end the main ReadingThread loop.
  • I just saw that ReadingThread.notifyFinished() is never called (in my case) but I don't understand why...

Do you have an idea ?

Use CopyOnWriteArrayList for Listeners

The class ListenerManager should use CopyOnWriteArrayList instead of ArrayList to remove the need for locking the list while informing the listeners. Better performance.

WebSocket.connect() performs network requests on UI thread on Android

Earlier tonight I switched to your WebSocket library since the one I was using had issues with wss:// on Android 5.0 (could be fixed but then it broke on older Android versions). After switching, I noticed that WebSocket.connect() seemingly performs network requests on the UI thread if not manually run on a different thread. The result is that I have to add lots of boilerplate code whenever I want to call my reconnectWebSocket() method. Other WebSocket libraries I looked at avoid doing this.

Is this something you would consider addressing? It would make it behave better on Android and result in cleaner code in the apps using it. Consider it a feature request, not technically an issue per se.

Other than that, it seems pretty solid so far. Good work!

Sending a byte array in pieces.

I'm trying to use the library to send an InputStream as byte[].

  • If I read and send the entire InputStream(~600kb) everything works. However, I want to be able to read and send smaller pieces (~4k).
  • If I add a Thread.sleep(100) after sending each binary message I works.

Here is the code I'm using:

// A text message arrived from the server.
public void onTextMessage(WebSocket websocket, String message) {  
  if (message != "listening")
    return;

  try {
    byte[] buffer = new byte[4096]; // 4k
    int read;
    while ((read = inputStream.read(buffer)) > 0) {
      if (read == 4096)
        socket.sendBinary(buffer);
      else {
        byte[] last = Arrays.copyOfRange(buffer, 0, read);
        socket.sendBinary(last);
      }
    }
  } catch (IOException e) {
    delegate.onError(e);
  } 
}
  • Is there a way to enable debugging?
  • Which thread is it using to send the audio? could that be the problem?

Provide MaxPayload.

Hello,

Can you provide a max payload property, which lets the library send it by fragments if it reaches the maximum payload.

Thanks,
Great work btw

Deadlock when sending some data in onConnected event

Stack traces:

"main@1" prio=5 tid=0x1 nid=NA waiting
  java.lang.Thread.State: WAITING
      at java.lang.Object.wait(Object.java:-1)
      at java.lang.Object.wait(Object.java:502)
      at com.neovisionaries.ws.client.WritingThread.queueFrame(WritingThread.java:191)
      at com.neovisionaries.ws.client.WebSocket.sendFrame(WebSocket.java:1918)
      at com.neovisionaries.ws.client.WebSocket.sendText(WebSocket.java:2106)


"ReadingThread@2526" prio=5 tid=0x15 nid=NA waiting
  java.lang.Thread.State: WAITING
     blocks WritingThread@2528
      at java.lang.Object.wait(Object.java:-1)
      at java.lang.Object.wait(Object.java:502)
      at com.neovisionaries.ws.client.WritingThread.queueFrame(WritingThread.java:191)
      at com.neovisionaries.ws.client.WebSocket.sendFrame(WebSocket.java:1918)
      at com.neovisionaries.ws.client.WebSocket.sendText(WebSocket.java:2106)
      ...
      at com.neovisionaries.ws.client.ListenerManager.callOnConnected(ListenerManager.java:189)
      at com.neovisionaries.ws.client.WebSocket.callOnConnectedIfNotYet(WebSocket.java:3207)
      at com.neovisionaries.ws.client.WebSocket.onReadingThreadStarted(WebSocket.java:3152)

"WritingThread@2528" prio=5 tid=0x16 nid=NA waiting for monitor entry
  java.lang.Thread.State: BLOCKED
     waiting for ReadingThread@2526 to release lock on <0x9e5> (a java.lang.Object)
      at com.neovisionaries.ws.client.WebSocket.onWritingThreadStarted(WebSocket.java:3173)
      at com.neovisionaries.ws.client.WritingThread.main(WritingThread.java:82)
      at com.neovisionaries.ws.client.WritingThread.run(WritingThread.java:56)

addListener onConnected never called

when connect successfully , onConnected/onTextMessage never called , i don't know why , how to solve it ?

.addListener(new WebSocketAdapter() {
@OverRide
public void onConnected(WebSocket websocket, Map<String, List> headers) {
Timber.e("onConnected-----------");
}

NPE when WebSocket.sendPing is called due to race condition

Hi,
I am using version 1.9 and ran into a race condition with the WebSocket.mWritingThread being null when calling WebSocket.sendPing. Here is the call stack:

Caused by java.lang.NullPointerException
       at com.neovisionaries.ws.client.WebSocket.sendFrame(WebSocket.java:1450)
       at com.neovisionaries.ws.client.WebSocket.sendPing(WebSocket.java:1859)

The reason this is happening is because I use WebSocket.connectAsynchronously in my setup thread but also have another thread that regularly call WebSocket.sendPing to keep my connection alive. The issue is rare as the timer on my pinging thread usually doesn't coincide with a newly created WebSocket object that hasn't yet finished its connection routine.

It would be great if there is a check in WebSocket.sendPing or WebSocket.sendFrame which ensures the mWritingThread is not null or throw an appropriate exception (not NPE).

Websocket interruption accessing "wss://echo.websocket.org"

After opening a websocket to "wss://echo.websocket.org", I encounter the following exception:
com.neovisionaries.ws.client.WebSocketException: Interruption occurred while a frame was being read from the web socket.

I can open a websocket to other servers without issue, so I suspect this is something particular to echo.websocket.org.

Support SSL Pinning

It would be convenient to have ssl pinning option to make web-socket validate server certificate against a keystore bundled in the application like it does DefaultHttpClient(see example here).

Also, this library can be used for implementation.

Authentication issue

Hi ,
When i am trying to connect to my server which requires username/password.
It respond me with


HTTP Version = HTTP/1.1
Status Code = 401
Reason Phrase = Unauthorized


  1. Do we have any kind of function by which we can add username/password to any initial connect to Websocket server ?

Here is my piece of code
try {

            HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
     TrustManager[] trustAllCerts = new TrustManager[]{
               new X509TrustManager() {
               public X509Certificate[] getAcceptedIssuers() {
                         X509Certificate[] myTrustedAnchors = new X509Certificate[0];
                        return myTrustedAnchors;
                  }
                @Override
                  public void checkClientTrusted(X509Certificate[] certs, String authType) {
                   }
                 @Override
                   public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }
               }
            };

        // Create an SSLContext that uses our TrustManager

        try {
            sc = SSLContext.getInstance("SSL");
             sc.init(null, trustAllCerts, null);
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Authenticator.setDefault(new Authenticator(){
            protected PasswordAuthentication getPasswordAuthentication() {
                String  username= "su";
                String passsetN="cws";
                return new PasswordAuthentication(username,passsetN.toCharArray());
            }});


        WebSocketFactory factory = new WebSocketFactory();
        factory.setSSLSocketFactory(sc.getSocketFactory());
        factory.createSocket("https://192.168.0.8/notification/echo.html")
            .addListener(new WebSocketAdapter() {
                @Override
                public void onTextMessage(WebSocket ws, String message) {
                    // Received a response. Print the received message.
                    System.out.println(message);

                    // Close the WebSocket connection.
                    ws.disconnect();
                }
            })
            .connect()
            .sendText("Hello.");
    } catch ( IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (OpeningHandshakeException e)
    {
        // Status line.
        StatusLine sl = e.getStatusLine();
        System.out.println("=== Status Line ===");
        System.out.format("HTTP Version  = %s\n", sl.getHttpVersion());
        System.out.format("Status Code   = %d\n", sl.getStatusCode());
        System.out.format("Reason Phrase = %s\n", sl.getReasonPhrase());

        // HTTP headers.
        Map<String, java.util.List<String>> headers = e.getHeaders();
        System.out.println("=== HTTP Headers ===");
        for (Entry<String, java.util.List<String>> entry : headers.entrySet())
        {
            // Header name.
            String name = entry.getKey();

            // Values of the header.
            List values = (List) entry.getValue();

            //if (values == null || values.size() == 0)
  //          {
                // Print the name only.
                System.out.println(name);
                continue;
            }

//            for (String value : values)
            {
                // Print the name and the value.
            //    System.out.format("%s: %s\n", name, value);
            }
        }

Callbacks are slow?

Whenever I'm streaming binary data, either the data is received slowly or the callback is taking a long time to get called.

Just a little context surrounding this, I'm streaming images in binary form from a server and rendering them on screen in Android. I know that there is some 'choking' going on with the Android client because I'm also streaming and rendering to a browser client and on the browser it's delay free. However when I stream to the Android client there is some delay.

Just to clarify, at the start of the stream there is absolutely no delay, but after around 5 seconds, the images received start to slow down (as in, they go in slow motion), which possibly points to the Android library doing some extra processing that slows down the callbacks being called (or my asynchronous LinkedBlockingQueue implementation being just badly done).

Here is some code:

public class MainActivity extends AppCompatActivity {

    private LinkedBlockingQueue<byte[]> linkedBlockingQueue = new LinkedBlockingQueue<byte[]>();
    private boolean keepRunning = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        new MyRenderer().start();
        ...
    }

    // Decodes and renders a bitmap
    private class MyRenderer extends Thread {
        @Override
        public void run() {
            // Keep running this thread
            while (keepRunning) {
                // .take() blocks until we have more data
                final byte[] bitmapArray = linkedBlockingQueue.take();
                final Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);

                // Set bitmap to an imageview
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        someImageView.setImageBitmap(bm);
                    }
                });
            }
        }
    }

    // We'll create a websocket listener as a class field and
    // set it to a websocket later
    WebSocketAdapter websocketAdapter = new WebSocketAdapter() {
        ....
        @Override
        public void onBinaryMessage(WebSocket websocket, byte[] bitmapArray) throws Exception {
            super.onBinaryMessage(websocket, bitmapArray);
            // Add the binary bitmap to the queue for processing in the above thread
            linkedBlockingQueue.put(bitmapArray);
        }
        ...
    }

   // Create websocket, set the websocketAdapter to a websocket, etc

}

Are there any pointers you could give me? Perhaps there's something that I'm doing stupidly wrong?

I would also be interested to know if you will be supporting a streaming websocket. As in one that I could easily perform websocket.read() for example, because that would mean I could pipe the data out to an OutputStream for forwarding or simply to read data in a new thread in an easy manner.


Library version: 1.22
Android compileSdkVersion: 23
Android minSdkVersion: 19

Fantastic library + documentation by the way 👍

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.