【问题标题】:android websocket client timeoutandroid websocket客户端超时
【发布时间】:2012-02-01 00:43:57
【问题描述】:

感谢阅读!

背景: 我正在为服务器开发一个 Android 客户端,该服务器的要求是应用程序需要与基于 WebSockets 的服务器持续来回交换消息。

实现:对于客户端,我使用weberknecht'sWebSocket Android 客户端库,而服务器基于Tornado

问题: 目前,我通过生成AsyncTaskonCreate 中调用initWebSocketClient。但是,我不断收到客户端超时异常。

Android 客户端:


private void initWebSocketClient() {
        Log.e(TAG, "initWebSocketClient");
        try {
            URI url = new URI("ws://192.168.207.84:8080/");
            WebSocket websocket = new WebSocketConnection(url);

            // Register Event Handlers
            websocket.setEventHandler(new WebSocketEventHandler() {
                    public void onOpen()
                    {
                            Log.e(TAG, "--open");
                    }

                    public void onMessage(WebSocketMessage message)
                    {
                            Log.e(TAG, "--received message: " + message.getText());
                    }

                    public void onClose()
                    {
                            Log.e(TAG, "--close"); 
                    }
            });

            // Establish WebSocket Connection
            websocket.connect();

            // Send UTF-8 Text
            websocket.send("hello world");

            // Close WebSocket Connection
            websocket.close();
        }
        catch (WebSocketException wse) {
                wse.printStackTrace();
        }
        catch (URISyntaxException use) {
                use.printStackTrace();
        }
    }

Tornado 服务器:


#!/usr/bin/env python

import tornado.ioloop
import tornado.web
import tornado.websocket

class EchoWebSocketHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        print "WebSocket opened"

    def on_message(self, message):
        self.write_message(u"You said: " + message)

    def on_close(self):
        print "WebSocket closed"

application = tornado.web.Application([
    (r"/", EchoWebSocketHandler),
])

if __name__ == "__main__":
    application.listen(8080)
    tornado.ioloop.IOLoop.instance().start()

客户端超时异常:


01-31 19:28:01.367: W/System.err(5668): de.roderick.weberknecht.WebSocketException: error while creating socket to ws://192.168.207.84:8080/
01-31 19:28:01.386: W/System.err(5668):     at de.roderick.weberknecht.WebSocketConnection.createSocket(WebSocketConnection.java:244)
01-31 19:28:01.386: W/System.err(5668):     at de.roderick.weberknecht.WebSocketConnection.connect(WebSocketConnection.java:83)
01-31 19:28:01.386: W/System.err(5668):     at com.sagar.websockclient.MainActivity.initWebSocketClient(MainActivity.java:55)
01-31 19:28:01.390: W/System.err(5668):     at com.sagar.websockclient.MainActivity.access$0(MainActivity.java:30)
01-31 19:28:01.390: W/System.err(5668):     at com.sagar.websockclient.MainActivity$WebSocketTask.doInBackground(MainActivity.java:75)
01-31 19:28:01.390: W/System.err(5668):     at com.sagar.websockclient.MainActivity$WebSocketTask.doInBackground(MainActivity.java:1)
01-31 19:28:01.390: W/System.err(5668):     at android.os.AsyncTask$2.call(AsyncTask.java:264)
01-31 19:28:01.390: W/System.err(5668):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-31 19:28:01.390: W/System.err(5668):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-31 19:28:01.390: W/System.err(5668):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-31 19:28:01.390: W/System.err(5668):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-31 19:28:01.390: W/System.err(5668):     at java.lang.Thread.run(Thread.java:856)
01-31 19:28:01.390: W/System.err(5668): Caused by: java.net.ConnectException: failed to connect to /192.168.207.84 (port 8080): connect failed: ETIMEDOUT (Connection timed out)
01-31 19:28:01.390: W/System.err(5668):     at libcore.io.IoBridge.connect(IoBridge.java:114)
01-31 19:28:01.394: W/System.err(5668):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
01-31 19:28:01.394: W/System.err(5668):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
01-31 19:28:01.394: W/System.err(5668):     at java.net.Socket.startupSocket(Socket.java:566)
01-31 19:28:01.394: W/System.err(5668):     at java.net.Socket.tryAllAddresses(Socket.java:127)
01-31 19:28:01.394: W/System.err(5668):     at java.net.Socket.(Socket.java:177)
01-31 19:28:01.394: W/System.err(5668):     at java.net.Socket.(Socket.java:149)
01-31 19:28:01.394: W/System.err(5668):     at de.roderick.weberknecht.WebSocketConnection.createSocket(WebSocketConnection.java:238)
01-31 19:28:01.394: W/System.err(5668):     ... 11 more
01-31 19:28:01.394: W/System.err(5668): Caused by: libcore.io.ErrnoException: connect failed: ETIMEDOUT (Connection timed out)
01-31 19:28:01.398: W/System.err(5668):     at libcore.io.Posix.connect(Native Method)
01-31 19:28:01.398: W/System.err(5668):     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85)
01-31 19:28:01.398: W/System.err(5668):     at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
01-31 19:28:01.398: W/System.err(5668):     at libcore.io.IoBridge.connect(IoBridge.java:112)
01-31 19:28:01.398: W/System.err(5668):     ... 18 more

有人可以帮我吗?

更新:添加 AutoBahn(Android 的 WebSocket 客户端库)实现细节:

AutoBahn 客户端


private void connect2() {
        mConnection = new WebSocketConnection();
        final String wsuri = "ws://192.168.0.137:8888/";
        String TAG = "ArticlesListActivity"; 

        try {
            mConnection.connect(wsuri, new WebSocketHandler() {
               @Override
               public void onOpen() {
                 Log.e(TAG, "Connected to: " + wsuri);
               }

               @Override
               public void onTextMessage(String payload) {
                  Log.e(TAG, "Message recieved = " + payload);
               }

               @Override
               public void onClose(int code, String reason) {
                  Log.e(TAG, "Connection Lost.");
               }
            });
         } catch (WebSocketException e) {

            Log.d(TAG, e.toString());
         }      
    }

有了这个库 - 我能够连接到服务器,但立即失去了连接。 (请参阅下面的“AutoBahn 客户端日志”。切换回 weberknecht 工作正常。我没有在任何地方明确调用 mConnection.disconnect()。所以我不知道连接是如何终止的。

AutoBahn 客户端日志


02-27 14:27:36.605: D/de.tavendo.autobahn.WebSocketConnection(27701): created
02-27 14:27:36.656: D/dalvikvm(27701): GC_FOR_ALLOC freed 164K, 4% free 9247K/9543K, paused 17ms
02-27 14:27:36.671: D/dalvikvm(27701): GC_FOR_ALLOC freed 7K, 4% free 9368K/9735K, paused 14ms
02-27 14:27:36.671: D/de.tavendo.autobahn.WebSocketReader(27701): created
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketConnection(27701): WS reader created and started
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketReader(27701): running
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketWriter(27701): created
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketConnection(27701): WS writer created and started
02-27 14:27:36.769: D/de.tavendo.autobahn.WebSocketReader(27701): run() : ConnectionLost
02-27 14:27:36.773: D/de.tavendo.autobahn.WebSocketReader(27701): ended
02-27 14:27:36.777: D/de.tavendo.autobahn.WebSocketConnection(27701): opening handshake received
02-27 14:27:36.777: E/ArticlesListActivity(27701): Connected to: ws://192.168.0.137:8888/
02-27 14:27:36.781: D/de.tavendo.autobahn.WebSocketConnection(27701): fail connection [code = 3, reason = WebSockets connection lost
02-27 14:27:36.784: D/de.tavendo.autobahn.WebSocketReader(27701): quit
02-27 14:27:36.788: D/de.tavendo.autobahn.WebSocketWriter(27701): ended
02-27 14:27:36.792: E/ArticlesListActivity(27701): Connection Lost.
02-27 14:27:36.792: D/de.tavendo.autobahn.WebSocketConnection(27701): worker threads stopped

【问题讨论】:

    标签: android client-server websocket tornado


    【解决方案1】:

    以下是我将如何开始解决此问题的方法:

    1. 您是否尝试在您的手机(设备)或模拟器上执行此操作?如果您尝试在手机上执行此操作并且您通过 3G 连接,则不会发生。在这种情况下,您尝试从 WAN 连接到一个内部 IP 地址,但该地址不起作用。

    2. 再次假设您是在设备上执行此操作,如果您通过 Wifi 连接,那就是另一回事了。确保可以访问192.168.207.84:8080 的服务器。一种快速测试连接的方法(从您的 PC):

      telnet 192.168.207.84 8080
      

      如果超时,您就知道您的服务器没有响应。这当然假设您的 PC 与您的 Wifi 网络位于同一子网

    3. 如果您尝试从仿真器执行此操作,请按照 [2] 中的步骤确保服务器可访问,并确保您的仿真器处于 (IP) 桥接模式。

    总而言之,主要超时的原因通常是因为缺乏服务器可用性(即缺乏连接性)。你没有提到你的网络细节,所以我在这里根据你尝试连接的 IP (192.168.207.84) 做了一些假设。

    【讨论】:

    • 太棒了!感谢@Marvin 的详细解释,这完全帮助我解决了问题。我正在使用设备,但我的服务器位于内部 IP 上。所以,现在我在同一个 wifi 上同时登录了服务器和设备,并且能够让它连接服务器!
    【解决方案2】:

    据我所知,Weberknecht 只支持 Hybi-10,而不是最终的 RFC6455 规范,而且更成问题的是,它是在主 (UI) 线程上联网吗?这通常是个坏主意,并且在 Android >2 上会失败。

    对于 Android 原生应用,有适用于 Android 的 Autobahn WebSockets

    https://github.com/oberstet/AutobahnAndroid

    它支持最终的 RFC6455,与 UI 和服务应用程序很好地集成,通过 WebSockets 提供 RPC 和 PubSub,等等。查看 GitHub 上的项目 README。

    免责声明:我是《高速公路》的作者。

    【讨论】:

    • 感谢您的信息!您的解决方案听起来很成熟,我在研究时回顾了一下,但我没有在这里看到适用于 Android 的 WebSocket:tavendo.de/autobahn/tutorials.html BTW,只是想知道它是否可以免费用于商业用途?
    • 顺便说一句,我为 websockets 网络活动生成了一个 AsyncTask,所以现在它工作正常。
    • 代码在 Apache 2.0 许可下.. 开源。 Rgd。 AsyncTask .. 使用您不需要的最新代码,因为不仅套接字读/写是在后台线程上完成的,而且初始套接字连接也是如此。直到最近,后一点才有所不同..确实在后台线程上读/写,但不是初始套接字连接..在最近的Android上导致“UI上的网络”线程问题。
    • Autobahn for Android 支持 WebSockets 协议草案版本 Hybi-10 直至最终 RFC6455。我不知道 Tornado WS 2.2 实现了什么..
    • 为我工作:Tornado 2.2 + 上面的代码 + Autobahn Android 的 Echo 客户端演示。可能是 Tornado 2.1 WS impl。可能太旧了.. 试试 2.2 ..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 2014-07-11
    • 2015-04-17
    • 2016-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多