代码之家  ›  专栏  ›  技术社区  ›  Russell Zornes

网络I/O挂在BlackBerry OS 5上

  •  3
  • Russell Zornes  · 技术社区  · 16 年前

    我在黑莓操作系统5上的网络I/O代码有一些问题。

    在我的I/O操作期间,我不断地得到零星的挂起和最终的TCP超时异常。

    问题是在执行实际I/O时。我有一个后台工作线程,为队列中的I/O请求提供服务。只有一个后台线程,因此所有请求都序列化到此线程上。

    在后台工作线程上调用完成委托,但是客户端可以通过 invokeLater 进行UI更新等。

    笔记:
    HttpRequest是我自己的类,它保存有关请求的数据。

    缓冲区大小=2048

    HttpConnection getConnectionForRequest(final HttpRequest inRequest) {
        final String url = inRequest.getURL();
        final int[] availableTransportTypes = 
            TransportInfo.getAvailableTransportTypes();
        final ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setPreferredTransportTypes(availableTransportTypes);
        connectionFactory.setConnectionMode(ConnectionFactory.ACCESS_READ);
        final ConnectionDescriptor connectionDescriptor = 
            connectionFactory.getConnection(url);
        HttpConnection connection = null;
        if (connectionDescriptor != null) {
            connection = (HttpConnection) connectionDescriptor.getConnection();
        }
        return connection;
    }
    
    public void run() {
        while (isRunning()) {
            // This blocks waiting on a request to appear in the queue.
            final HttpRequest request = waitForRequest(); 
            final HttpConnection connection = getConnectionForRequest(request);
            final MutableData data = new MutableData();
            final InputStream inputStream = connection.openInputStream();
            final byte[] readBuffer = new byte[BUFFER_SIZE];
            int chunkSize;
            // *** The following read call sporadically hangs and eventually throws
            //  a TCP timeout exception.
            while((chunkSize = inputStream.read(readBuffer, 0, BUFFER_SIZE)) != -1) {
                data.appendData(readBuffer, 0, chunkSize);
            }
            mDelegate.receivedDataForRequest(request, data);
        }
    }
    

    当它挂起时,它总是在大约30秒后抛出一个TCP超时错误。 频繁发生足以说明更深层的问题。

    编辑:

    我试过的模拟器是。。。

    • 风暴9550
    • 巡回赛9630
    • 粗体9000
    • 珍珠9100
    • 曲线8530

    我有一个曲线8530和风暴9550设备,它发生在这两个以及。

    任何帮助都将不胜感激。

    4 回复  |  直到 15 年前
        1
  •  0
  •   Byron Whitlock    16 年前

    你可以试试 Available() 方法。即使您正在序列化一个backround线程上的数据,看起来请求是在主线程中创建的。你可能会遇到一些奇怪的比赛情况。

        2
  •  0
  •   Marc Novakowski    16 年前

    是否可以添加一些日志以显示设备选择用于每个连接的传输类型?也许这是一个传输选择API选择一个它认为可以工作的传输的例子,而事实上它不工作。

        3
  •  0
  •   Peter Mortensen Pieter Jan Bonestroo    15 年前

    有人建议在我的网络I/O线程中放置一个暂停检测器,当检测到暂停时,中断线程并重新启动请求。我在开始请求之前启动一个计时器,当我读取每个数据块时,我重置计时器。如果计时器在我可以读取一个块之前就过期了,我假设网络已经停止,我中断线程并重新开始该请求。

    我已经这样做了,它确实改善了事情,至少减少了延迟,我必须等待,然后才能继续请求,因为我不必等待TCP超时,这可能需要很长时间。

    中断当前的I/O操作并重新启动似乎可以使网络恢复正常运行一段时间,通常在再次暂停之前可以正常运行几分钟。我在调试时将暂停记录到控制台中,得到了很多暂停。

    这是一个非常奇怪的问题,我不完全满意的失速检测解决方案。这似乎只是掩盖了问题,但它确实让我在某种程度上解决了我遇到的长期拖延。

        4
  •  0
  •   Michael Donohue Reno    15 年前

    read(byte[], int, int) 在我使用过的所有黑莓操作系统上-4.5到6.0。
    我为InputStream编写了一个适配器 变成一个电话 read()

    如果您阅读轮辋规格 读取(字节[],int,int) 上面写着:

    类InputStream的read(b,off,len)方法只是重复调用read()方法。如果第一个这样的调用导致IOException,则从对read(b,off,len)方法的调用返回该异常。如果对read()的任何后续调用都会导致IOException,则会捕获该异常并将其视为文件的结尾;读取到该点的字节存储到b中,并返回异常发生前读取的字节数。鼓励子类提供此方法的更有效实现。

    我按照这个规范编写了自己的版本,遇到了同样的问题。我认为问题在于,一旦有数据可用,该方法就需要返回而不阻塞。唯一的办法就是利用 available() 可用() ,我想这只是电话 读取()

    public int read(byte[] bts, int st, int len) throws IOException {
        if(len == 0) {
            return 0;
        }
        int readByte = this.read();
        if(readByte == -1) {
            return 0;
        }
        bts[st] = (byte)readByte;
        return 1;
    }