简体   繁体   中英

Java socket read inputstream without blocking

I have a little problem with implementing socket connection between Android and IOS. While I'm using my application to connect two Android running devices everything works fine. But when I have to receive some data from Iphone app my readStream function is blocking and I can receive all data after the other part close the socket and it that way I can't return any response back to it. Here is what I am using for listening :

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();
        }
    }
}

and here is the function which I am using to convert InputStream to 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();
}

The both Iphone / Android app works like this:

  • First it creates Socket and send data to other device and close the OutputStream.
  • The second part is parsing the byte array and then return response using the same socket.

Any ideas how to change my functions so I can read the inputstream without blocking?

EDIT:

So the problem was on IOS side, it seems that Apple API require to close both streams of the created socket : read/write so the byte array can be send, which seems really stupid, because in that way the iphone app can't receive and parse my response.

Contrary to the comment in your edit, it's your fault, not Apple's. You need to redesign your API. Your readBytes() method reads the stream until its end, which only happens when the peer closes the connection. If you just want to read some bytes, read(byte[]) already does that, and tells you how many, without requiring end of stream. I would just throw this method away.

With the experience of programming for RIM OS, I think all these IO operations should be performed in a different thread. The main UI thread would be asked to call another application thread using invokeLater() type methods where you check whether your asynchronous operation is complete and take appropriate action. That way, your code to read the input stream must be run in a separate thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM