在Android应用程序中使用哪个WebSocket库?[关闭]


131

我想将服务添加到我的Android应用程序中,该应用程序在后台运行并保持WebSocket连接(可能需要几个小时甚至几天),并定期将一些数据发送到服务器。

现在似乎有一堆用于Java的WebSocket库,但我不确定应该使用哪个库:

此外,还有一个用于Android 的本地socket.io客户端库:

使用socket.io Android客户端对我来说很方便,因为无论如何我打算将nodejs / socket.io用于Web前端。但是本机客户还很年轻,并且有几个未解决的问题。除此之外,据我了解,Android应用程序没有使用socket.io客户端库的任何好处(除了与socket.io 1.0服务器兼容),因为可以在客户端确保WebSocket支持。

我的要求如下:

  • 与Android API 9及更高版本的兼容性
  • 通过SSL进行连接的可能性
  • 长时间保持连接,而无需保持永久唤醒
  • 与可用的nodejs websocket服务器实现或与socket.io的兼容性

有什么建议是适合这些要求的库吗?


也许是气氛。看到这个问题
罗勒·布尔克

2
我不是WebSocket和Atmosphere方面的专家。我只知道Atmosphere是用旧的,在许多项目中都使用了Push功能,包括WebSocket支持。我唯一的经验是间接构建Vaadin Web应用程序。Vaadin使用Atmosphere来实现自动推送功能。但是请注意,WebSocket仍然相对较新,在其简短的历史记录中对其定义,规格和各种实现进行了许多更改。因此,无论您如何前进,都应期待“问题”。
罗勒·布尔克

2
仅供参考,高速公路就在那儿,他们有一个华丽的网站。但是,在花时间安装并尝试运行它之前,请注意“未实现安全的WebSocket”。下一个。
cloudurfin

1
我没有足够的声誉来发表评论,因此,我已经按照您在问题中提到的相同要求进行了写作,因此我将其写为答案,并且okhttp帮助我满足了所有要求。自从3.5版引入以来,它就支持Web套接字,因此使用okHttp(Web服务调用+ Web套接字支持)具有另一个优势。这是开始的链接。< medium.com/@ssaurel/… >
Kaleem Patel

7
这样的问题不应该被解决。
马丁·伯杰

Answers:


123

一些注意事项。

  • koush / AndroidAsync不执行RFC 6455要求的关闭握手。请参阅了解详情。

  • Tyrus项目可在Android上运行,但请确保其许可证(带有CPE的CDDL 1.1和GPL 2)及其大小(通过ProGuard减小WebSocket客户端jar的大小)符合您的要求。另请注意,当文本大时,Tyrus可能会引发异常(这可能是一个错误)。请参阅了解详情。

  • JettyJetty用户邮件列表中有2年的电子邮件线程说:“我们目前没有与Android兼容的Jetty 9 WebSocket客户端。有计划尝试将Jetty WebSocket客户端从JDK 7移植到JDK 5/6(用于android)使用,但比完成我们对JSR-356 Java WebSocket API(javax.websocket)的实现的优先级低。” Jetty当前有关其WebSocket Client API的文档未提及任何有关Android的内容。

  • codebutler / android-websocket不会执行RFC 6455要求的关闭握手,并且可能在关闭时引发异常。看到这个

  • Atmosphere / wasync使用AsyncHttpClient / async-http-client作为其WebSocket实现。因此,应该改为提及AsyncHttpClient / async-http-client。

  • firebase / TubeSock不验证Sec-WebSocket-Accept。这违反了RFC 6455。另外,TubeSock在构建短信时也有错误。如果将多字节UTF-8字符用于文本消息,则迟早会遇到该错误。见第3期喜悦-IM / Android的DDP约TubeSock问题的一个长长的清单。

考虑点

选择用Java编写的WebSocket客户端实现时的注意事项:

  1. 合规性。少数实现未实现关闭握手 RFC 6455要求。(如果未实现关闭握手,会发生什么?请参阅。)
  2. 必需的Java版本。Java SE 5、6、7、8还是Java EE?即使在Android上也可以使用?
  3. 大小。一些实现具有许多依赖性。
  4. s支持。
  5. HTTP代理支持。
  6. 通过HTTP代理支持wss。参见图2 HTML5 Web套接字如何与代理服务器交互中的以了解WebSocket客户端库为支持基于HTTP代理的wss而必须做的事情。
  7. SSL配置的灵活性SSLSocketFactory并且SSLContext应该能够不受不必要的限制地加以利用。
  8. 打开握手中的自定义HTTP标头,包括基本身份验证。
  9. HTTP代理协商中的自定义HTTP标头,包括在代理服务器上的身份验证。
  10. 是否可以发送所有帧类型(连续,二进制,文本,关闭,乒乓和乒乓)。大多数实现都没有为开发人员提供发送碎片帧自发 pong帧的方法手动。
  11. 侦听器界面用于接收各种WebSocket事件。不良的界面会使开发人员感到沮丧。丰富的界面可帮助开发人员编写健壮的应用程序。
  12. 能够查询WebSocket状态RFC 6455定义了CONNECTING,OPEN,CLOSING和CLOSED状态,但是很少有实现以定义的方式维护其内部状态转换。
  13. 能够设置套接字连接的超时值。(相当于Socket.connect(SocketAddress endpoint, int timeout) method)
  14. 能够访问底层的原始套接字
  15. 直观易用的API
  16. 是否有据可查
  17. RFC 7692(WebSocket的压缩扩展)支持(又名permessage-deflate)。
  18. 重新导向(3xx)支持。
  19. 摘要式身份验证支持。

nv-websocket-client涵盖了以上所有内容,最后两个除外。另外,它的小巧但方便的功能之一是定期发送ping / pong帧。只需调用setPingInterval/setPongInterval方法即可实现(请参见 JavaDoc)。

免责声明:Takahiko Kawasaki是nv-websocket-client的作者。


1
nv-websocket-client库是否仍在开发中?我遇到TooTallNate / Java-WebSockets的自动断开连接问题,错误为1006,没有原因。.此nv-websocket还能解决吗?
Ankit Bansal,2015年

1
至于1006,规范(RFC 6455)规定,端点不得在Close控制帧中将代码设置为状态代码。这意味着代码是在客户端生成的。您可以通过WebSocketListener的onDisconnected方法和onError方法获得有关断开连接的更多信息。方法为您提供了一个实例。调用其方法以查看问题所在。onErrorWebSocketExceptiongetError()
川崎隆彦

7
对于wss,我尝试了okhttp和autobahn(也怀疑此答案中的自我提升)。高速公路很简单,但是没有SSL。OkHttp几乎没有零(合并)文档(2016年2月)。我浪费大量时间阅读他们的代码和异常,因为我不愿意采用变通方法(例如将超时设置为0或关闭传入的消息)来获得一个简单的示例。抛弃这两个(和我的挫败感),我发现nv(令人耳目一新)有据可查;它没有大惊小怪。
cloudurfin

1
对Square / okhttp的新websockets支持有何想法?medium.com/square-corner-blog/...
scorpiodawg

2
我不知道有关OkHttp的详细信息。抱歉,我正忙于作为Authlete,Inc.的创始人(“ API安全初创公司Authlete筹集了120万美元的种子资金 ”),我不能花时间研究OkHttp并更新考虑点列表。关于自我回答以来的更改,请参阅CHANGES.md。请注意,nv-websocket-client只是我的爱好,而OkHttp似乎是一个拥有138个贡献者的大型项目。
川崎隆彦

4

其他一些注意事项:

Tyrus可在Android上使用。但是,它在Android 5.0中使用的SSL库存在错误,并且SSL握手失败。应该在较新的Android版本中解决此问题,但是由于许多设备上未更新Android,这可能对您来说是个问题。

根据其他Websocket实现的SSL实现方式,这可能也是一个问题。

AndroidAsync没有此SSL问题。它确实有其他问题,例如无法设置超时


3

a)将此文件添加到gradle文件中

compile 'com.github.nkzawa:socket.io-client:0.3.0'

b)在“应用程序活动”中添加以下行:

    public class MyApplication extends Application {
     private Socket mSocket;
        {
            try {
               mSocket = IO.socket(Config.getBaseURL());

            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            }
        }

        public Socket getSocket() {
            return mSocket;
        }
}

c)在您调用WebSocket的活动中添加以下功能:

     private void websocketConnection() {
            //Get websocket from application
            MyApplication app = (MyApplication ) getApplication();
            mSocket = app.getSocket();
            mSocket.on(Socket.EVENT_CONNECT, onConnect);
            mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
            mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
            mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
            mSocket.on("messageFromServer", onNewLocation);
            mSocket.connect();
        } 


    private Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            runOnUiThread(() -> {
                if (!isConnected) {

                    RequestSocket mRequestSocket = new RequestSocket();

                    mRequestSocket.setToken("anil_singhania");
                   /* your parameter */
                    mSocket.emit("messageFromClient", new Gson().toJson(mRequestSocket));
                    Log.i("Socket Data", new Gson().toJson(mRequestSocket));
                    isConnected = true;
                }
            });
        }
    };

    private Emitter.Listener onDisconnect = args -> runOnUiThread(() -> {
        isConnected = false;
       /* Toast.makeText(getApplicationContext(),
                R.string.disconnect, Toast.LENGTH_LONG).show();*/
    });

    private Emitter.Listener onConnectError = args -> runOnUiThread(() -> {
         /*   Toast.makeText(getApplicationContext(),
            R.string.error_connect, Toast.LENGTH_LONG).show()*/
    });

    private Emitter.Listener onNewLocation = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            runOnUiThread(() -> {


            });
        }
    };

这不支持ws://协议。
Girish Bhutiya
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.