C Server receiving EPIPE from java client, but not from a Python one


S

Saptarshi

Hello,
My server, written in C has some command sequences. For example to get
it to evaluate a string and return some data, the client must send
(where dop is the sockets dataoutputstream). (The server reads ands
ends Big endian)

dop.writeInt(RConnection.CMD_EVAL);
dop.writeInt(expression.length());
dop.writeBytes(expression);
dop.flush();

the client then reads,
int serlen = dip.readInt();
byte[] b = new byte[serlen];
dip.read(b);

and b now contains the data. However, there might be some info
messages too, so the client then reads
(*) int k = dip.readInt(). //corresponds to the length of the info
string that wil be sent.

On the C side, when it attempts to write the int for (*) to read, the
write command returns -1 and ERRNO is 32 (EPIPE). Also, the value of
k, is some number fixed across sessions but nothing like the original.
e.g when the int that the server will write is: 0 0 0 e (big
endian), the client has read 85 1 0 0. However, the value in 'b' is
correct.

The python client does not have any problems. It is the Java one that
troubles me.
The socket has no options and this is TCP/IP on the same machine (OS X
10.5, Java 1.5)

Thank you for your time
Saptarshi(please could you cc to (e-mail address removed))
 
Ad

Advertisements

M

Mark Space

Saptarshi said:
The python client does not have any problems. It is the Java one that
troubles me.
The socket has no options and this is TCP/IP on the same machine (OS X
10.5, Java 1.5)

Really, I don't understand what you are asking. We'll need some code,
preferably an SSCCE:

http://sscce.org/

The Java API emphasizes cohesion as a design principle. It uses smaller
classes that try to do just one thing, or a smaller related group of
things. Thus, the same functionality tends to be spread out over more
classes.

The following (untested) code illustrates how you might read an
arbitrary integer for a socket.


Socket sock = new Socket();
// make a connection...
SocketChannel chan = sock.getChannel();
ByteBuffer buf = ByteBuffer.allocateDirect( 16 * 1024 );
chan.read( buf );
int value = buf.getInt();

If this isn't what you are asking, you'll have to clarify.

Thank you for your time
Saptarshi(please could you cc to (e-mail address removed))


Please send all replies to c.l.j.programmer. This is a collective
discussion group.
 
E

EJP

Saptarshi said:
the client then reads,
int serlen = dip.readInt();
byte[] b = new byte[serlen];
dip.read(b);

Here you are ignoring the value returned by the read, and assuming that
b[] was filled by the read, which isn't very likely if 'serlen' is
large. You should use DataInputStream.readFully() here.
On the C side, when it attempts to write the int for (*) to read, the
write command returns -1 and ERRNO is 32 (EPIPE).

This is a Java forum, but that errno has precisely one meaning: the peer
has already closed the connection and you are still writing to it. So
there is something wrong with the implementation of your application
protocol.

Also, the value of
k, is some number fixed across sessions but nothing like the original.
e.g when the int that the server will write is: 0 0 0 e (big
endian), the client has read 85 1 0 0.

That's another indication that your peers are out of sync.
However, the value in 'b' is
correct.

Try that again with readFully().
(please could you cc to (e-mail address removed))

No, I couldn't do that.
 
S

Saptarshi

My apologies. It was an endian issue. I had been adjusting the code
for endiannenes and forgot to modify one variable name. So it was
expecting the wrong number of bytes.
I was debugging for 5hrs, feeling frustrated, I sent this email.
Sorry for the confusion, thanks for the assistance.

Regards
Saptarshi
 
Ad

Advertisements

M

Mark Space

Saptarshi said:
My apologies. It was an endian issue. I had been adjusting the code
for endiannenes and forgot to modify one variable name. So it was
expecting the wrong number of bytes.
I was debugging for 5hrs, feeling frustrated, I sent this email.
Sorry for the confusion, thanks for the assistance.

Regards
Saptarshi

If you use a byte buffer, like I show above, you can use
order(BIG_ENDIAN) or order(LITTLE_ENDIAN) and not have to worry about
converting each primitive you read.
 

Top