5

I have a client which is connecting to a server. The server and the client exchange datas in string format. The problem is that, the server does not take '\n' character at the end of the message and because of this the client blocked in readLine() method. Unfortunately the server-side can't be changed. How can read from stream that kind of message which does not have '\n' at the end?

My client code:

public class json 
{

    private static Socket socket;

    public static void main(String args[])
    {

        String sendMessage = "";

        Gson gson = new Gson();
        JSON_package authentication = new JSON_package();
        authentication.setType("Identifying");
        authentication.setSource("exampleClient");

        Package_Parser pp = new Package_Parser();

        sendMessage = gson.toJson(authentication);


        sendMessage = authentication.buildPackage(sendMessage);

        try
        {
            String host = "host_address";
            int port = port_number;
            InetAddress address = InetAddress.getByName(host);

            System.out.println("Connecting.");

            socket = new Socket(address, port);
            System.out.println("Connected.");

            //Send the message to the server
            OutputStream os = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os);
            BufferedWriter bw = new BufferedWriter(osw);
            bw.write(sendMessage);
            bw.flush();
            System.out.println("Message sent to the server : "+sendMessage);

            //Get the return message from the server
            InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuffer buffer = new StringBuffer();
            String message = br.readLine();

            message = pp.Parser(message);

            System.out.println("Message received from the server : " +message);
        }
        catch (Exception exception) 
        {
            exception.printStackTrace();
        }
        finally
        {
            //Closing the socket
            try
            {
                socket.close();
                System.out.println("Closed.");
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}
Genesist
  • 141
  • 2
  • 3
  • 7
  • consider reading result using read(char[] cbuf, int off, int len) method. And parsing it to string manually – Anton Jul 17 '13 at 21:45

3 Answers3

5

You can try to use ready and read(char c) methods. Here is one example:

StringBuffer sb = new StringBuffer();
while (br.ready()) {
    char[] c = new char[] { 1024 };
    br.read(c);
    sb.append(c);
}
fmodos
  • 4,472
  • 1
  • 16
  • 17
2

The easiest solution is to read the message character per character, but the main problem here is to know when the message is complete. In a line-oriented protocol this is simple, the newline that was sent is the "separator" between messages. Without, there are two possible situations where this problem is easy to solve:

Case 1: the message always has a fixed character at the end, that can't occur in the message

// let's pretend ! is the end of message marker
final char endMarker = '!';

// or of course StringBuffer if you need to be treadsafe
StringBuilder messageBuffer = new StringBuilder();
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
    char c = (char)value;
    // end?  jump out
    if (c == endMarker) {
        break;
    }
    // else, add to buffer
    messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();

Case 2: the message has a fixed length

// let's pretend message is always 80 long
int messageLength = 80;

StringBuilder messageBuffer = new StringBuilder();
int charactersRead = 0;
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
    char c = (char)value;
    // end?  jump out
    if (++charactersRead >= messageLength) {
        break;
    }
    // else, add to buffer
    messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();

In both cases you'll have to add some code to check the sanity of what you received, you may have received EOF during read.

If there is no obvious message separator and message have a variable length it will be a lot harder.

fvu
  • 32,488
  • 6
  • 61
  • 79
0

The point of readLine() is to read data where it really is guaranteed that the input will end with a newline. Generally, when parsing input, there has to be some token - some character or combination of characters in the input, which you can use to decide whether to

  • Wait for more input
  • Do something with the information you've gotten already
    • And possibly decide whether to go back to waiting for more input afterwards

If you cannot guarantee that a newline will be sent, then readLine() is the wrong tool for the job. Use something like the character-array read method of InputStreamReader instead. You will have to iterate the array of characters you read in, and figure out when you have enough input to work with. You could also use the one-character-at-a-time read() method of InputStreamReader which will result in simpler but probably less efficient code.

If you use the character-array version of read(), and if you go back to collecting input after parsing some, don't forget to put whatever is left over when you do get enough to parse back into the queue to handle on the next round.

Tim Boudreau
  • 1,741
  • 11
  • 13