Java Socket Bug: Reading Strings from Socket's InputStream
Asked Answered
F

2

6

I'm using a Socket to communicate with a ServerSocket. Strings are being sent from the server to my Socket. Each distinct line is a message that, when parsed, contains information. To read these lines of text, a Scanner is used.

The problem is that data is coming in "spurts." Although the Server is sending data continuously and evenly, the data read by the Scanner on the client side seems to pause, read in a bunch of messages (30-40) at once, and then pause again. It repeats this cycle indefinitely.

If I increase the rate at which data is sent, the duration of the pauses decreases; if I slow down the data (to 1 message per second), the bug persists and the pauses become very long. It's almost as if the Socket waits for its buffer to overflow before it sends any data to the Scanner; then flushes everything and waits for the overflow again. However, if I decrease the size of the Socket's buffer, nothing changes at all.

It should be noted that I've used Scanner and Socket in this method before - from the Server side - and everything worked as desired. Additionally, I a) tried this with a BufferedReader like the Java Tutorials (no change in the bug) and b) printed a list of Server transmissions into a file, and read from the file in the same way, and the program worked as expected (constant rate of message reception, etc) so the problem seems to be in the Socket itself.

So: How do I fix this behavior? I'm out of ideas atm and I really don't know what's going on.

CODE (As requested):

// In try block
// Makes the connection
Socket connection = new Socket(TARGET_MACHINE, PORT_NUMBER);
Scanner reader = new Scanner(connection.getInputStream());

// In new Thread
// In run()
while(!finished) // Boolean exit strategy
{
    if(reader.hasNextLine())
        Sring message = reader.nextLine();
}

That's how I connect and retrieve the Strings.

Also, the Strings that I am receiving are usually about 20-40 characters long.

Femur answered 10/6, 2011 at 18:10 Comment(3)
post some code, to see what's going on.Roentgenoscope
It's not a bug, it's a feature. Probably you have some caching on the sender side which you have to flush explicitly.Thrice
Your TCP stack may be combining multiple messages into single packets for network traffic optimization. 30-40 messages would fit into a single packet, if the messages were short enough. Without code and more specifics on how long "very long" is for your pauses, it will be hard to diagnose.Spectrometer
A
2

Do you flush the stream every time you write to it from the server side? It could be buffering the output and not writing it to the stream until it reaches a certain threshold.

Aldric answered 13/6, 2011 at 18:29 Comment(1)
Assuming you're using an OutputStream, it's just .flush(). OutputStream os = socket.getOutputStream(); os.flush(); There are similar methods for stream writers. BufferedWriter bw = ...; bw.flush();Aldric
S
2

Are you maybe using readLine to read data?

Here is excerpt from javadoc which might be interesting to you:

Since this method continues to search through the input looking for a line separator, it may buffer all of the input searching for the line to skip if no line separators are present.

Can you attach client and server code to see what is wrong? It would be good that you use very simple byte-per-byte reader to check is the stream from server with pauses in transport, maybe the problem is with the way how you write data into server's socket... without code is hard to guess :)

Semiquaver answered 10/6, 2011 at 19:37 Comment(1)
Yeah, I noticed that line, but I'd been using Scanner to parse Socket messages before and I hadn't noticed any problem. The main problem seemed to be in the Socket connection; I wanted to see if I could fix that first.Femur
A
2

Do you flush the stream every time you write to it from the server side? It could be buffering the output and not writing it to the stream until it reaches a certain threshold.

Aldric answered 13/6, 2011 at 18:29 Comment(1)
Assuming you're using an OutputStream, it's just .flush(). OutputStream os = socket.getOutputStream(); os.flush(); There are similar methods for stream writers. BufferedWriter bw = ...; bw.flush();Aldric

© 2022 - 2024 — McMap. All rights reserved.