Socket communication on Win32 vs Linux

T

Tom Dyess

Hi,

I created a newsgroup reader object that communicates with a newsgroup
server and caches articles. It works wonderfully when I run it on a Windows
box, but acts strangely when on a Linux box. Could someone help me, please.

Here is the offending code:

Pseudocode:
- call buildConnection() which creates the socket and sets the in and out
variable pointers
- buildConnection() calls rawAuthenticate() which uses the raw in and out
variables to log into the newsgroup server

the problem is with the rawAuthenticate() method. In Linux, it hangs on the
second in.readLine() as if the server didn't respond to the printline.
You'll see in buildConnection() that I constructed the PrintWriter with the
autoFlush parameter to true. I can't figure out the difference.

Server dialog:
Windows:
200 Powered by Highwinds Software -- http://www.highwinds-software.com/
(Tornado v1.0.6)
AUTHINFO USER account
381 More Authentication Required

Linux:
200 Powered by Highwinds Software -- http://www.highwinds-software.com/
(Tornado v1.0.6)
AUTHINFO USER account
(hangs here - in.readLine() just sits there as if there is no line to read
and eventually sends a timeout message 503.


/**
* Create a socket, set the out and in variables and authenticate to the
server
* based on the object's host and port variables
*
*/
static private synchronized void buildConnection() {
try {
sock = new Socket(host, port);
sock.setKeepAlive(true);
out = new PrintWriter(sock.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
rawAuthenticate();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* Send dialog to a connected socket to authenticate to a newsgroup server
* based on the object's login and password variables
* @return if authentication was successful
*/
private static synchronized boolean rawAuthenticate() {
boolean result = true;
String line;
try {
out.println(); // Tell the server there is someone here
if (debug) {System.out.println();}
line = getIn().readLine(); // the header
if (debug) {System.out.println(line);}
// 480 Authentication required for command
out.println("AUTHINFO USER " + login);
if (debug) {System.out.println("AUTHINFO USER " + login);}
line = in.readLine(); // HERE IS THE PROBLEM - THIS NEVER READS
if (debug) {System.out.println(line);}
if (line.startsWith("381")) {
 
E

Esmond Pitt

Tom said:
out = new PrintWriter(sock.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

NNTP - RFC 977 - uses an 8-bit character. Readers and Writers are for
16-bit characters. You should be using Input/OutputStreams for this.
 
S

Stefan Schulz

NNTP - RFC 977 - uses an 8-bit character. Readers and Writers are for
16-bit characters. You should be using Input/OutputStreams for this.

That is just plainly false. You should use Readers, since those do the
conversion between 8-Bit and 16-Bit for you, and are aware of Character
Sets. My guess is that the OP has an encoding, or line termination based
problem, but without more information there is no way to be sure.
 
F

Filip Larsen

Tom Dyess wrote
I created a newsgroup reader object that communicates with a newsgroup
server and caches articles. It works wonderfully when I run it on a Windows
box, but acts strangely when on a Linux box. Could someone help me,
please.

Wild guess: make sure you use CR LF to terminate lines send to the
newsserver, ie. don't rely on println to do it for you.


Regards,
 
T

Tom Dyess

Stefan Schulz said:
That is just plainly false. You should use Readers, since those do the
conversion between 8-Bit and 16-Bit for you, and are aware of Character
Sets. My guess is that the OP has an encoding, or line termination based
problem, but without more information there is no way to be sure.

What kind of information do you need? I've tried everything and am stumped.
Could it be the difference between CRLF and just CR (or LF) on *Nix systems?
Since the server is the same, I didn't think that would matter.

Some info:
Dev box (where it works) is WinXP
Server box (where it doesn't work) is i386 Linux Redhat 9.0

Lemme know of anything else you can think of. The strange thing is the
initial println I send works fine, the server replies with the host line
"200 Powered by Highwinds Software ..."
 
T

Tom Dyess

Tom Dyess said:
Hi,

I created a newsgroup reader object that communicates with a newsgroup
server and caches articles. It works wonderfully when I run it on a
Windows box, but acts strangely when on a Linux box. Could someone help
me, please.

Here is the offending code:

Pseudocode:
- call buildConnection() which creates the socket and sets the in and out
variable pointers
- buildConnection() calls rawAuthenticate() which uses the raw in and out
variables to log into the newsgroup server

the problem is with the rawAuthenticate() method. In Linux, it hangs on
the second in.readLine() as if the server didn't respond to the printline.
You'll see in buildConnection() that I constructed the PrintWriter with
the autoFlush parameter to true. I can't figure out the difference.

Server dialog:
Windows:
200 Powered by Highwinds Software -- http://www.highwinds-software.com/
(Tornado v1.0.6)
AUTHINFO USER account
381 More Authentication Required

Linux:
200 Powered by Highwinds Software -- http://www.highwinds-software.com/
(Tornado v1.0.6)
AUTHINFO USER account
(hangs here - in.readLine() just sits there as if there is no line to read
and eventually sends a timeout message 503.


/**
* Create a socket, set the out and in variables and authenticate to the
server
* based on the object's host and port variables
*
*/
static private synchronized void buildConnection() {
try {
sock = new Socket(host, port);
sock.setKeepAlive(true);
out = new PrintWriter(sock.getOutputStream(), true);
in = new BufferedReader(new
InputStreamReader(sock.getInputStream()));
rawAuthenticate();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* Send dialog to a connected socket to authenticate to a newsgroup server
* based on the object's login and password variables
* @return if authentication was successful
*/
private static synchronized boolean rawAuthenticate() {
boolean result = true;
String line;
try {
out.println(); // Tell the server there is someone here
if (debug) {System.out.println();}
line = getIn().readLine(); // the header
if (debug) {System.out.println(line);}
// 480 Authentication required for command
out.println("AUTHINFO USER " + login);
if (debug) {System.out.println("AUTHINFO USER " + login);}
line = in.readLine(); // HERE IS THE PROBLEM - THIS NEVER READS
if (debug) {System.out.println(line);}
if (line.startsWith("381")) {


It was the println functionality that was the problem. To solve it, I used

out.print(line + "\r\n");
out.flush();


Thanks a bunch for your help! What an unfortunate inconsistancy. Fortunately
I created a printLine() function for all my calls so I can debug, so it was
a simple fix.
 
J

John C. Bollinger

Tom said:
It was the println functionality that was the problem. To solve it, I used

out.print(line + "\r\n");
out.flush();


Thanks a bunch for your help! What an unfortunate inconsistancy. Fortunately
I created a printLine() function for all my calls so I can debug, so it was
a simple fix.

It's only partially an inconsistency. PrintWriter.println() is defined
to terminate lines with the system-dependent end-of-line sequence
(available to you from System.getProperty("line.seperator"), should you
ever want it yourself). It was behaving exactly as documented on both
systems.

Java has great features for writing platform independant programs, but
it doesn't absolve the programmer from taking platform dependencies into
account. This is especially true when you need your Java program to
speak some narrowly-defined dialect, such as a network protocol.


John Bollinger
(e-mail address removed)
 
S

Steve Horsley

Tom said:
It was the println functionality that was the problem. To solve it, I used

out.print(line + "\r\n");
out.flush();

You have another problem lurking: You are not specifying the character
encoding when you create the reader and writer. This can lead to strange
characterset conversion problems.

Steve
 
T

Tom Dyess

John C. Bollinger said:
It's only partially an inconsistency. PrintWriter.println() is defined to
terminate lines with the system-dependent end-of-line sequence (available
to you from System.getProperty("line.seperator"), should you ever want it
yourself). It was behaving exactly as documented on both systems.

Java has great features for writing platform independant programs, but it
doesn't absolve the programmer from taking platform dependencies into
account. This is especially true when you need your Java program to speak
some narrowly-defined dialect, such as a network protocol.


John Bollinger
(e-mail address removed)

John,

Does this occur when building the .class files? I build it on the Win32
machine and deployed it on the Linux box. Had I compiled it on the Linux
box, would it have worked?
 
T

Tom Dyess

Steve Horsley said:
You have another problem lurking: You are not specifying the character
encoding when you create the reader and writer. This can lead to strange
characterset conversion problems.

Steve

Do I want the character encoding of the NNTP server or the J2EE server? I'm
assuming the NNTP server since I'm talking to it, but want to make sure
before I make the change.
 
E

Esmond Pitt

Stefan said:
That is just plainly false. You should use Readers, since those do the
conversion between 8-Bit and 16-Bit for you, and are aware of Character
Sets. My guess is that the OP has an encoding, or line termination based
problem, but without more information there is no way to be sure.

I disagree, and it is certainly not 'just plainly false'. Why use
Readers & Writers which 'do the conversion' for you, when you could use
Input/OutputStreams and have no 8/16-bit conversions to worry about? The
OP's program is supposed to implement an external protocol defined in
8-bit bytes in RFC 977. The 16-bit characters that Java uses and the
mapping that Readers and Writers do are of no concern to RFC 977 or
implementations of NNTP servers. It is up to the client to implement the
correct protocol, and using Readers and Writers is a step in the wrong
direction. It also introduces the issue of making sure the correct
conversion is used as another poster noted. Why bother?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top