Best practice for reading / writing to a java server socket

11,542

There are basically three ways to do network I/O:

  1. Blocking. In this mode reads and writes will block until they can be fulfilled, so if you want to do both simultaneously you need separate threads for each.

  2. Non-blocking. In this mode reads and writes will return zero (Java) or in some languages (C) a status indication (return == -1, errno=EAGAIN/EWOULDBLOCK) when they cannot be fulfilled, so you don't need separate threads, but you do need a third API that tells you when the operations can be fulfilled. This is the purpose of the select() API.

  3. Asynchronous I/O, in which you schedule the transfer and are given back some kind of a handle via which you can interrogate the status of the transfer, or, in more advanced APIs, a callback.

You should certainly never use the while (in.available() > 0)/sleep() style you are using here. InputStream.available() has few correct uses and this isn't one of them, and the sleep is literally a waste of time. The data can arrive within the sleep time, and a normal read() would wake up immediately.

Share:
11,542
Schifty
Author by

Schifty

Updated on June 20, 2022

Comments

  • Schifty
    Schifty almost 2 years

    How do you design a read and write loop which operates on a single socket (which supports parallel read and write operations)? Do I have to use multiple threads? Is my (java) solution any good? What about that sleep command? How do you use that within such a loop?

    I'm trying to use 2 Threads:

    Read

    public void run() {
        InputStream           clientInput;
        ByteArrayOutputStream byteBuffer;
        BufferedInputStream   bufferedInputStream;
        byte[]                data;
        String                dataString;
        int                   lastByte;
    
        try {
            clientInput         = clientSocket.getInputStream();
            byteBuffer          = new ByteArrayOutputStream();
            bufferedInputStream = new BufferedInputStream(clientInput);
    
            while(isRunning) {  
    
                while ((lastByte = bufferedInputStream.read()) > 0) {
                    byteBuffer.write(lastByte);
                }
                    data       = byteBuffer.toByteArray();  
                    dataString = new String(data);
                    byteBuffer.reset();     
            }   
    
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    Write

    public void run() {
        OutputStream clientOutput;
        byte[]       data;
        String       dataString;
    
        try {
            clientOutput = clientSocket.getOutputStream();
    
            while(isOpen) { 
    
                if(!commandQueue.isEmpty()) {
                    dataString = commandQueue.poll();
                    data       = dataString.getBytes();
                    clientOutput.write(data);
                }                   
                Thread.sleep(1000);
            }       
            clientOutput.close();           
        } 
        catch (IOException e) {
            e.printStackTrace();
        } 
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    

    Read fails to deliver a proper result, since there is no -1 sent. How do I solve this issue?

    Is this sleep / write loop a good solution?