🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.lang.java.programmer
6 messages
6 total messages Started by Rosinger Mon, 11 Feb 2002 12:07
Problems with blocking socket
#158
Author: Rosinger
Date: Mon, 11 Feb 2002 12:07
68 lines
3109 bytes
Hi all,

I am experimenting with sockets in Java. I have this little program that 
I've written:

------------------------------------------------------------------------
import java.net.*;
import java.io.*;

public class client
{
	public static void main (String[] args) throws IOException
	{
		String username = "foo";
		String password = "bar";
		Socket socket = new Socket ("mail", 110); // mail is my local POP3 server
		BufferedReader in = new BufferedReader (new InputStreamReader 
(socket.getInputStream()));
		PrintWriter out = new PrintWriter (new OutputStreamWriter 
(socket.getOutputStream()));

		// send command to server
		out.print (username + "\n");
		out.flush();

		// read response
		String response = "";
		String line;
		while ((line = in.readLine()) != null)
		{
			response += line;
		}
		
		System.out.println (response);

		in.close();
		out.close();
		socket.close();
	}
}
------------------------------------------------------------------------

Nothing too complicated, but there is a little problem: the while loop 
keeps blocking and does NOT return null when there's nothing to read 
from the socket.

If, for example, I replace the host to "www" (my local web server) and 
request to get an HTML file like:

out.print ("GET " + "/index.html" + " HTTP/1.0\n\n")
out.flush();

The while loop gets back the HTML file line by line, and when the entire 
file has been read, it does NOT block anymore.

I find it very strange that for the mail server example, the while loop 
does NOT return null when there's nothing to read from the socket and 
keeps blocking, while the web server example DOES return null and 
returns when there's nothing to read from the socket.

Does anyone know what the difference between the mail server and the web 
server is? Or, how to solve this problem?

Thanks in advance,

Cheers,

Joshua
Re: Problems with blocking socket
#159
Author: Jon Skeet
Date: Mon, 11 Feb 2002 12:45
51 lines
2872 bytes
Rosinger <rosinger@optushome.com.au> wrote:
> 		String response = "";
> 		String line;
> 		while ((line = in.readLine()) != null)
> 		{
> 			response += line;
> 		}

This bit of code is horrible, by the way - use a StringBuffer.
See http://www.pobox.com/~skeet/java/string.html
 		
> 		System.out.println (response);
> 
> 		in.close();
> 		out.close();
> 		socket.close();
> 	}
> }

These close calls should be part of a finally block, so they get 
executed even if an IO exception is thrown.

Neither of these are major problems for small test code, but I thought 
I'd just raise them in case you weren't aware of them.

> Nothing too complicated, but there is a little problem: the while loop 
> keeps blocking and does NOT return null when there's nothing to read 
> from the socket.

Indeed - and that's correct. It should only return null when the socket 
has been closed (by either end).

> I find it very strange that for the mail server example, the while loop 
> does NOT return null when there's nothing to read from the socket and 
> keeps blocking, while the web server example DOES return null and 
> returns when there's nothing to read from the socket.

Nope, the web server is closing the socket in this case, hence the 
return of null.
 
> Does anyone know what the difference between the mail server and the web 
> server is? Or, how to solve this problem?

In a mail server, the protocol should tell you how much to read - eg by 
finishing with a line of just "." - but this depends on the protocol you 
want to use.

-- 
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too
Re: Problems with blocking socket
#160
Author: Gordon Beaton
Date: Mon, 11 Feb 2002 12:49
51 lines
2757 bytes
On Mon, 11 Feb 2002 23:07:34 +1100, Rosinger wrote:
> I am experimenting with sockets in Java. I have this little program
> that I've written:

[...]
> 		while ((line = in.readLine()) != null)
> 		{
> 			response += line;
> 		}

> Nothing too complicated, but there is a little problem: the while
> loop keeps blocking and does NOT return null when there's nothing to
> read from the socket.

It is behaving exactly as it should.

> Does anyone know what the difference between the mail server and the
> web server is? Or, how to solve this problem?

BufferedReader.readLine() returns null at EOF. That means that the end
of the stream has been reached, that there will *never* be any more
data available. Not that there is nothing to read "for the moment".

As long as the connection is still active, readLine() will block until
a complete line has been received, at which point it will be returned
to the caller.

When you tested with a web server, it sent you the file and closed the
connection, so EOF was reached and readLine() returned null.

When you tested with a mail server, the remote did not close the
connection because the session is not yet over; it is waiting for
additional commands. You would have run into the same problem if you
had specified HTTP/1.1 when you connected to the web server.

You need to use different criteria for determining when the end of the
data has been reached. For example the pop server might tell you the
length of the mail before transferring it, and there may be a prompt
that appears afterwards.

You should read the protocol definitions so you can deal with this
situation properly:

  pop: http://www.ietf.org/rfc/rfc1939.txt
  http: http://www.ietf.org/rfc/rfc2616.txt

/gordon

-- 
[ do not send me private copies of your followups ]
g o r d o n . b e a t o n @ e r i c s s o n . c o m
Re: Problems with blocking socket
#161
Author: Manish Jethani
Date: Mon, 11 Feb 2002 14:37
18 lines
1515 bytes
Rosinger wrote:

>                 out.print (username + "\n");

If you really want to auth, it should be:
                  out.print("USER " + username
                    + "\r\n"); /* end with \r\n */

>                 while ((line = in.readLine()) != null)

The USER command of pop3 will return just a single line.  And
the connection does not get closed (unlike in HTTP), so you
should read just one line and don't wait for EOF
(readLine() == null).

Check the POP3 rfc - http://www.ietf.org/rfc/rfc1939.txt .

Manish
Re: Problems with blocking socket
#162
Author: Timo Kinnunen
Date: Mon, 11 Feb 2002 15:45
56 lines
2513 bytes
Jon Skeet <skeet@pobox.com> wrote:

> Rosinger <rosinger@optushome.com.au> wrote:
>>           System.out.println (response);
>> 
>>           in.close();
>>           out.close();
>>           socket.close();
>>      }
>> }
> 
> These close calls should be part of a finally block, so they get 
> executed even if an IO exception is thrown.

What is the best way to close multiple streams? This ofcourse depends 
on whether the method has been declared to throw an IOException. I've 
considered a lot of different approaches, but I haven't found a winner 
yet. Some of the better:

Doesn't throw an IOException:

    try {
      // ...
    } finally { 
      closeIfNonNullAndIgnoreIOException(in);
      closeIfNonNullAndIgnoreIOException(out);
      closeIfNonNullAndIgnoreIOException(socket);
    }

Throws an IOException:

    try {
      // ...
    } catch(IOException e) {
      closeIfNonNullAndIgnoreIOException(in);
      in = null;
      closeIfNonNullAndIgnoreIOException(out);
      out = null;
      closeIfNonNullAndIgnoreIOException(socket);
      socket = null;
      throw e;
    } finally { 
      try {
        if(in != null) in.close();
      } finally { 
        try {
          if(out != null) out.close();
        } finally {
          if(socket != null) socket.close();
        }
      }
    }

-- 
No address munging in use. I like the smell of nuked accounts in the 
morning.
Re: Problems with blocking socket
#164
Author: Jon Skeet
Date: Mon, 11 Feb 2002 17:16
37 lines
2428 bytes
Timo Kinnunen <timo.kinnunen@bigfoot.com> wrote:
> Jon Skeet <skeet@pobox.com> wrote:
> 
> > Rosinger <rosinger@optushome.com.au> wrote:
> >>           System.out.println (response);
> >> 
> >>           in.close();
> >>           out.close();
> >>           socket.close();
> >>      }
> >> }
> > 
> > These close calls should be part of a finally block, so they get 
> > executed even if an IO exception is thrown.
> 
> What is the best way to close multiple streams? This ofcourse depends 
> on whether the method has been declared to throw an IOException. I've 
> considered a lot of different approaches, but I haven't found a winner 
> yet. Some of the better:
> 
> Doesn't throw an IOException:
> 
>     try {
>       // ...
>     } finally { 
>       closeIfNonNullAndIgnoreIOException(in);
>       closeIfNonNullAndIgnoreIOException(out);
>       closeIfNonNullAndIgnoreIOException(socket);
>     }

That's the kind of thing I normally use - IOUtil.close in my case. I 
normally make it log any throwables caught, basically.

-- 
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads