【问题标题】:Which WebSocket library to use in Android app? [closed]在 Android 应用程序中使用哪个 WebSocket 库? [关闭]
【发布时间】:2015-08-13 09:05:45
【问题描述】:

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

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

另外还有一个原生的socket.ioAndroid客户端库:

  • nkzawa/socket.io-client.java 来自 GitHub 的描述:用于 Java 的全功能 Socket.IO 客户端库,兼容 Socket.IO v1.0 及更高版本。

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

我的要求如下:

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

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

【问题讨论】:

  • 也许是Atmosphere。见this Question。
  • 我不是 WebSocket 和 Atmosphere 方面的专家。我只知道 Atmosphere 已经过时了,在许多项目中用于 Push 功能,包括 WebSocket 支持。我唯一的经验是间接的,构建Vaadin 网络应用程序。 Vaadin 使用 Atmosphere 的自动推送功能。但请注意,WebSocket 仍然相对较新,在其短暂的历史中对其定义、规范和各种实现进行了许多更改。所以不管你怎么走,都要期待“问题”。
  • 仅供参考,高速公路就在那里,他们有一个华丽的网站。但是在您花时间安装并尝试运行它之前,不会注意到“未实现安全 WebSockets”。下一步。
  • 我没有足够的声誉来发表评论,因此我将其写为答案,因为我已经完成了您在问题中提到的相同要求,并且 okhttp 帮助我满足了所有要求。从 3.5 版本开始就支持 web sockets,所以使用 okHttp(web service calls + web sockets support)是一个额外的优势。这是开始的链接。 medium.com/@ssaurel/…>
  • 这样的问题不应该被关闭。

标签: android node.js websocket


【解决方案1】:

一些笔记。

  • koush/AndroidAsync 不执行RFC 6455 所需的closing handshake。详情请见this。

  • Project Tyrus 适用于 Android,但请确保其许可证 (CDDL 1.1 and GPL 2 with CPE) 和大小 (Reducing WebSocket client jar size with ProGuard) 符合您的要求。另请注意,当文本大小很大时,Tyrus 可能会抛出异常(这可能是一个错误)。详情请见this。

  • Jetty:2 年前,jetty-users 邮件列表中的 email thread 说 “我们目前没有兼容 Android 的 Jetty 9 WebSocket 客户端。有计划尝试向后移植Jetty WebSocket Client 从 JDK 7 到 JDK 5/6 供 android 使用,但它的优先级低于完成我们对 JSR-356 Java WebSocket API (javax.websocket) 的实现。” Jetty 当前的 document 关于它的WebSocket Client API 没有提及任何关于 Android 的内容。

  • codebutler/android-websocket 不执行closing handshake 所需的RFC 6455,并且可能在关闭时抛出异常。见this。

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

  • firebase/TubeSock 不验证 Sec-WebSocket-Accept。这违反了RFC 6455。此外,TubeSock 在构建文本消息方面存在错误。如果您将多字节 UTF-8 字符用于文本消息,您迟早会遇到该错误。有关 TubeSock 问题的长列表,请参阅 delight-im/Android-DDP 中的 Issue 3。

注意事项

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

  1. 合规性。不少实现没有实现RFC 6455 要求的closing handshake。 (如果关闭握手没有实现会怎样?见this。)
  2. 所需的 Java 版本。 Java SE 5、6、7、8 还是 Java EE?甚至可以在 Android 上运行?
  3. 尺寸。一些实现有很多依赖项。
  4. wss 支持。
  5. HTTP 代理 支持。
  6. wss over HTTP 代理 支持。请参阅How HTML5 Web Sockets Interact With Proxy Servers 中的图 2,了解 WebSocket 客户端库必须做什么才能支持 wss over HTTP 代理。
  7. SSL 配置的灵活性。 SSLSocketFactory 和 SSLContext 应该可以在没有不必要限制的情况下使用。
  8. opening handshake 中的自定义 HTTP 标头,包括基本身份验证。
  9. HTTP 代理协商中的自定义 HTTP 标头,包括代理服务器上的身份验证。
  10. 能够发送所有帧类型(连续、二进制、文本、关闭、ping 和 pong)。大多数实现不为开发人员提供手动发送fragmented frames 和不请自来 pong frames 的方法。
  11. 侦听器接口 接收各种 WebSocket 事件。糟糕的界面使开发人员感到沮丧。丰富的界面可帮助开发人员编写强大的应用程序。
  12. 能否查询WebSocket状态。 RFC 6455 定义了 CONNECTING、OPEN、CLOSING 和 CLOSED 状态,但很少有实现以定义的方式保持其内部状态转换。
  13. 可以设置套接字连接的超时值。 (相当于Socket.@987654344@(SocketAddress endpoint, int timeout)方法的第二个参数)
  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 的作者。

【讨论】:

  • nv-websocket-client 库是否仍在开发中?我遇到了 TooTallNate/Java-WebSockets 的自动断开问题,错误 1006 并且没有任何原因.. 这个 nv-websocket 也解决了吗?
  • 对于 1006,规范 (RFC 6455) 规定代码不得由端点在关闭控制帧中设置为状态代码。这意味着代码是在客户端生成的。您可以通过WebSocketListener的onDisconnected方法和onError方法获取更多关于断开连接的信息。 onError 方法为您提供了一个 WebSocketException 实例。调用它的getError() 方法看看是什么问题。
  • 对于 wss,我尝试了 okhttp 和 autobahn(也怀疑这个答案中的自我提升)。高速公路很容易,但没有 SSL。 OkHttp 几乎没有(合并)文档(2016 年 2 月)。我浪费了很多时间阅读他们的代码和他们的异常,因为我不知道解决方法(比如将超时设置为 0,或关闭传入的消息)来获得一个简单的示例工作。抛弃这两个(以及我的挫败感),我发现 nv (令人耳目一新)有据可查;它毫不费力地工作。
  • 对 Square/okhttp 的新 websockets 支持有什么想法吗? medium.com/square-corner-blog/…
  • 我不知道 OkHttp 的详细信息。不好意思我作为Authlete, Inc.("API security startup Authlete raises $1.2m in seed funding")的创始人太忙了,抽不出时间去看看OkHttp,更新一下考虑点列表。关于我回答后的变化,请参阅CHANGES.md。请注意,nv-websocket-client 只是我的爱好,而 OkHttp 似乎是一个拥有 138 个贡献者的大项目。
【解决方案2】:

其他一些注意事项:

Tyrus 适用于 Android。然而,它在 Android 5.0 中使用的 SSL 库是有缺陷的,而且 fail SSL handshakes。这应该在较新版本的 Android 中得到修复,但由于许多设备上没有更新 Android,这对您来说可能是个问题。

取决于 SSL 是如何为其他 websocket 实现实现的,这也可能是一个问题。

AndroidAsync 没有这个 SSL 问题。它确实有其他问题,例如not being able to set timeouts。

【讨论】:

    【解决方案3】:

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

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

    b) 在 Application Activity 中添加这些行:

        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://协议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 2011-08-21
    相关资源
    最近更新 更多