【问题标题】:Java socket read inputstream without blockingJava套接字读取输入流而不阻塞
【发布时间】:2012-08-16 17:07:45
【问题描述】:

我在实现 Android 和 IOS 之间的套接字连接时遇到了一点问题。当我使用我的应用程序连接两个运行 Android 的设备时,一切正常。但是当我必须从 Iphone 应用程序接收一些数据时,我的 readStream 函数被阻塞,我可以在另一部分关闭套接字后接收所有数据,这样我就无法返回任何响应。这是我用来听的:

try {
    serverSocket = new ServerSocket(5000);
    Log.d("","CREATE SERVER SOCKET");
} catch (IOException e) {
     e.printStackTrace();
}

while(state){
    try {
        if(serverSocket!=null){
            client = serverSocket.accept();
            client.setKeepAlive(true);
            client.setSoTimeout(10000);

            // LOGS
            Log.w("READ","is connected : "+client.isConnected());
            Log.w("READ","port : "+client.getPort());
            Log.w("READ","ipadress : "+client.getInetAddress().toString());



            InputStream is = client.getInputStream();

            Log.w("READ","is Size : "+is.available());

            byte[] bytes = DNSUtils.readBytes(is);
            Log.v("","-------------------------");
            for(int i=0;i<bytes.length;i++){
                Log.w("READ","bytes["+i+"] : "+bytes[i]);
            }
            Log.v("","-------------------------");

            try {
                Log.w("READ","packetType : "+bytes[4]);

                if(bytes!=null)
                    DNSUtils.getPacketType(bytes[4], bytes, client);

            } catch(Exception e){
                e.printStackTrace();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
        Log.v("","IOException");
        ResponseERR pack = new ResponseERR();
        ResponseERR.errorMsg = "Socket TimeOut exception!";
        byte[] packet = pack.createNewPacket();

        try {
            if(client!=null){
                OutputStream out = client.getOutputStream();
                out.write(packet);
                out.flush();
                client.shutdownOutput();
                client.close();
                Log.e("READDATAFROMSOCKET","ResponseERR Send.");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
}

这是我用来将InputStream 转换为Byte Array 的函数:

public static byte[] readBytes(InputStream inputStream) throws IOException {
    // this dynamically extends to take the bytes you read
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();

    // this is storage overwritten on each iteration with bytes
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];

    // we need to know how may bytes were read to write them to the byteBuffer
    int len = 0;
    while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
    }

    // and then we can return your byte array.
    return byteBuffer.toByteArray();
}

Iphone / Android 应用程序的工作方式如下:

  • 首先它创建 Socket 并将数据发送到其他设备并关闭 OutputStream。
  • 第二部分是解析字节数组,然后使用同一个套接字返回响应。

任何想法如何更改我的功能,以便我可以读取输入流而不会阻塞?

编辑:

所以问题出在 IOS 方面,似乎 Apple API 需要 关闭创建的套接字的两个流:读/写所以字节 可以发送数组,这看起来很愚蠢,因为这样 iphone 应用无法接收和解析我的回复。

【问题讨论】:

  • 您可以在单独的线程中运行readStream 方法。
  • 我在单独线程上运行的服务中运行此代码。
  • 与苹果无关。这是你的错。 您的代码会一直读取到流结束,因此您的代码需要对等方关闭连接才能发生,

标签: java android sockets inputstream


【解决方案1】:

与您编辑中的评论相反,这是您的错,而不是 Apple 的。你需要重新设计你的 API。您的 readBytes() 方法读取流直到其结束,这仅在对等方关闭连接时发生。如果您只想读取 一些 字节,read(byte[]) 已经这样做了,并告诉您有多少,而无需结束流。我只想把这个方法扔掉。

【讨论】:

    【解决方案2】:

    凭借 RIM OS 的编程经验,我认为所有这些 IO 操作都应该在不同的线程中执行。将要求主 UI 线程使用 invokeLater() 类型的方法调用另一个应用程序线程,您可以在其中检查异步操作是否完成并采取适当的操作。这样,您读取输入流的代码必须在单独的线程中运行。

    【讨论】:

    • 我在一个单独线程上运行的服务中创建监听方法,而不是在主 UI 线程中。
    • 那么,正在抽取数据的一方应该定期刷新它,以便另一方继续读取它。否则,如果读取线程在流上被阻塞(如果生产者比消费者慢),会有什么问题?这是冻结设备还是类似的东西?
    • 设备不会死机,问题是当 Iphone 应用程序向我发送数据时,我只能在它向我发送数据后关闭套接字的情况下在 while 循环中读取它。否则我会收到套接字超时异常。我需要在不阻塞的情况下读取输入流,因为inputStream.read(buffer); 正在阻塞并等待直到套接字关闭,不知道为什么。
    • 您是否尝试在客户端频繁刷新(即使对于 android 客户端也可以刷新)?
    • 你的意思是发送数据时刷新OutputStream?
    猜你喜欢
    • 2010-11-23
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 2011-07-17
    • 2018-07-26
    • 2021-03-03
    • 1970-01-01
    • 2016-02-11
    相关资源
    最近更新 更多