2013-02-10 131 views
0

在我的Android应用程序,我有这段代码:安卓:快速HTTP请求

  while(testCase){ 
      for(HttpPut put : httpPut){ 
       try { 
        httpclient.execute(put, responseHandler); 
       } catch (ClientProtocolException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
       } catch (IOException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
       } 

       try { 
        Thread.sleep(150); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } 

我的目标是有预建HTTPPut请求列表(在这种情况下:“httpPut”)发出每150毫秒依次进行,直到被告知破坏(由“testCase”布尔值破坏)。它在技术上起作用,但在实际执行中有时会有很多延迟。在每个请求的接收端,它可能会滞后3-5秒才会收到另一个HTTPPut。而手机的屏幕会更糟。我在扩展的AsyncTask类中运行此代码。

我的问题是,有什么办法可以使我的代码更在执行该代码以更精确地火;要尽可能准确地接近每150毫秒?谢谢阅读!

编辑: 至于建议在另一个线程运行,我尝试添加以下代码:

... 
       performOnBackgroundThread(new Runnable(){ 

        @SuppressWarnings("unchecked") 
        @Override 
        public void run() { 
         try { 
          final DefaultHttpClient httpclient = new DefaultHttpClient(); 
          final ResponseHandler responseHandler = new BasicResponseHandler(); 

          httpclient.execute(put, responseHandler); 
         } catch (ClientProtocolException e1) { 
          // TODO Auto-generated catch block 
          e1.printStackTrace(); 
         } catch (IOException e1) { 
          // TODO Auto-generated catch block 
          e1.printStackTrace(); 
         } 
        } 

       }); 
... 

public static Thread performOnBackgroundThread(final Runnable runnable) { 
    final Thread t = new Thread() { 
     @Override 
     public void run() { 
      try { 
       runnable.run(); 
      } finally { 

      } 
     } 
    }; 
    t.start(); 
    return t; 
} 

但我的申请很快与“I /流程(18762)崩溃:发送信号PID:18762 SIG:9“,我也遇到了一堆这些错误。

02-10 00:14:58.639: W/SingleClientConnManager(18762): Invalid use of SingleClientConnManager: connection still allocated. 
02-10 00:14:58.639: W/SingleClientConnManager(18762): Make sure to release the connection before allocating another one. 
02-10 00:14:58.639: W/SingleClientConnManager(18762): Invalid use of SingleClientConnManager: connection still allocated. 
02-10 00:14:58.639: W/SingleClientConnManager(18762): Make sure to release the connection before allocating another one. 
02-10 00:14:58.647: W/System.err(18762): java.net.SocketException: Socket closed 
02-10 00:14:58.647: W/System.err(18762): at libcore.io.Posix.recvfromBytes(Native Method) 
02-10 00:14:58.647: W/System.err(18762): at libcore.io.Posix.recvfrom(Posix.java:131) 
02-10 00:14:58.647: W/System.err(18762): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164) 
02-10 00:14:58.647: W/System.err(18762): at libcore.io.IoBridge.recvfrom(IoBridge.java:513) 
02-10 00:14:58.647: W/System.err(18762): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488) 
02-10 00:14:58.647: W/System.err(18762): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46) 
02-10 00:14:58.647: W/System.err(18762): at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240) 
02-10 00:14:58.647: W/System.err(18762): at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103) 
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:191) 
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:82) 
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:174) 
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:180) 
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:235) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:259) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:279) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:428) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:653) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627) 
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616) 
02-10 00:14:58.663: W/System.err(18762): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:79) 
02-10 00:14:58.663: W/System.err(18762): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:116) 
02-10 00:14:58.671: W/System.err(18762): java.net.SocketTimeoutException 
02-10 00:14:58.671: W/System.err(18762): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:491) 
02-10 00:14:58.671: W/System.err(18762): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46) 
02-10 00:14:58.671: W/dalvikvm(18762): threadid=17: thread exiting with uncaught exception (group=0x40d03300) 

编辑#2:

02-10 00:38:08.639: W/System.err(20100): java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer) 
02-10 00:38:08.639: W/System.err(20100): at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:552) 
02-10 00:38:08.639: W/System.err(20100): at libcore.io.IoBridge.recvfrom(IoBridge.java:516) 
02-10 00:38:08.639: W/System.err(20100): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488) 
02-10 00:38:08.647: W/System.err(20100): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46) 
02-10 00:38:08.647: W/System.err(20100): at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:191) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:82) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:174) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:180) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:235) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:259) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:279) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:428) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:653) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627) 
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616) 
02-10 00:38:08.647: W/System.err(20100): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:79) 
02-10 00:38:08.647: W/System.err(20100): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:116) 
02-10 00:38:08.647: W/System.err(20100): Caused by: libcore.io.ErrnoException: recvfrom failed: ECONNRESET (Connection reset by peer) 
02-10 00:38:08.647: W/System.err(20100): at libcore.io.Posix.recvfromBytes(Native Method) 
02-10 00:38:08.647: W/System.err(20100): at libcore.io.Posix.recvfrom(Posix.java:131) 
02-10 00:38:08.647: W/System.err(20100): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164) 
02-10 00:38:08.647: W/System.err(20100): at libcore.io.IoBridge.recvfrom(IoBridge.java:513) 
02-10 00:38:08.647: W/System.err(20100): ... 19 more 

回答

2

你真的不能100%保证您的服务器将看到一个150毫秒的每个更新,由于网络的指标变化。你最好的选择是尝试比你想要的更快的事情,例如每100ms发送一个新的请求,并希望服务器至少每隔100ms收到一次更新。而且,如果你正在快速发送请求,请考虑使用基于TCP的UDP。根据我的经验,TCP请求需要更长的时间,因为确保数据包已交付,但如果您丢失了一两个数据包,对您而言,如果您的平均案例性能更好,例如, 90%的时间您每100ms看到一次更新。

你很可能会看到目前因为你正在运行到前面的请求例如在服务器上的延迟如果req1需要200ms,req2需要350ms,req3需要120ms,那么在服务器上,您将不会每隔150ms看到一次请求。前几个请求尤其如此,其中网络性能可能在5-10次请求后显着更差(例如1-2秒)。

我会建议建立一个第二的AsyncTask类,您快速产卵断第一的AsyncTask(见this对于一些潜在的指导)。但是,如果您如此迅速地生成新的请求对象,那么这可能只会导致您遇到一些线程限制。

最大的问题是你确定你做了正确的事情?你不会让网络芯片组的睡眠时间缩短150ms(这可能需要150ms以上才能完成执行!),那为什么还要打扰许多个人请求呢?为什么不使用类似于保持打开状态的套接字(例如,可能是Google http长轮询)?

+0

谢谢你真的想出来的响应!不幸的是,我根本无法控制接收端,所以我不认为我可以修改UDP的TCP端口(除非我错了,我对它不熟悉)。 幸运的是,接收器是在同一个网络我的手机上,所以在毫秒平应该是非常低的,对不对?这是有道理的,我的手机可能会搞砸,因为睡眠的过程比150ms的时间本身更长。如果它有任何兴趣,这个应用程序的iPhone相当于能​​够在同一网络上发射150ms请求。 – BarryBostwick 2013-02-10 07:23:02