Non-blocking method for reading writing objects to sockets


S

Sameer

The methods writeObject and readObject of socket class are blocking
one. i.e. if we create a ObjectInputStream object using
new ObjectInputStream(socket.getInputStream()), the methods blocks
until it gets some stream stuff.
What is the corresponding non-blocking mthod so as to include in
non-blocking programming?
 
Ad

Advertisements

J

Joseph Dionne

Sameer said:
The methods writeObject and readObject of socket class are blocking
one. i.e. if we create a ObjectInputStream object using
new ObjectInputStream(socket.getInputStream()), the methods blocks
until it gets some stream stuff.
What is the corresponding non-blocking mthod so as to include in
non-blocking programming?

Technically there are not non blocking socket write methods in any
language. There is either room enough in the socket write MCB to hold
the data, allowing the method to return, or there is not enough room,
and an error is returned to indicate a failure.

Either increase your transmit buffer size, which I believe defaults to
32kb, or find out why the data is not being transmitted to the network.
If your Objects are larger then 32kb, increasing the transmit buffer
is the answer. If your Objects are smaller than 32kb, then you most
likely have other issues.

joseph
 
J

John C. Bollinger

Sameer said:
The methods writeObject and readObject of socket class are blocking
one. i.e. if we create a ObjectInputStream object using
new ObjectInputStream(socket.getInputStream()), the methods blocks
until it gets some stream stuff.

It sounds like you are unsatisfied with this aspect of the constructor's
behavior: "A serialization stream header is read from the stream and
verified. This constructor will block until the corresponding
ObjectOutputStream has written and flushed the header." (API docs)
What is the corresponding non-blocking mthod so as to include in
non-blocking programming?

ObjectInputStreams are incompatible with non-blocking programming, and
indeed, there can be no general-purpose, non-blocking alternative for
which the minimal unit of transfer is a whole object. This is because
it is impossible ever to guarantee to read an arbitrary object without
blocking. (Consider, for instance, one that is too large to fit in the
socket's kernel-level I/O buffer.)

The stream header check performed by ObjectInputStream's constructor
could conceivably be pushed back to the first read, allowing the
constructor to avoid blocking, but it wouldn't gain you much because the
reads themselves cannot be nonblocking.
 
S

Sameer

Hello,
I have designed one chatting software using non-blocking features of
java.
In this project I transferred data using non-blocking methods of Buffer
related classes.
Now I decided to change the design of the projct and I like to send the
data as objects over the network using readObject and writeObject
methods of socket class.
For this purpose, I have to create instances ObjectInputStream and
ObjectOutputStream.
As per our previous discussion on this group the constructors of these
classes are BLOCKING methods.
Then how to carry out this? Is there any alternative or I have to
continue with blocking approach i.e. a multithreaded chatting server
where each thread handles one connection?
The code given under is not working...
Please suggest some remedy.


import java.io.*'
import java.net.*;
import java.nio.channels.*;;
import java.util.*;

public class PollingChatServer {
private int port;

private Vector sockets = new Vector();

public PollingChatServer(int port) throws IOException {
this.port = port;
listen();
}

private void listen() {
try {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.socket().bind(new InetSocketAddress(port));
System.out.println("Listening on port " + port);
while (true) {
System.out.println("Looking for connections...");
SocketChannel sc = ssc.accept();
if (sc != null) {
System.out.println("Connection from " + sc);
sockets.addElement(sc);
}
for (Enumeration e = sockets.elements(); e.hasMoreElements();) {
SocketChannel socch = null;
try {
socch = (SocketChannel) (e.nextElement());
Socket soc = socch.socket();
System.out.println("In for loop before creation of ois...");
//a blocking method ois
ObjectInputStream ois = new ObjectInputStream(soc.getInputStream());
Message messageObject = (Message) ois.readObject();
String str = messageObject.message;
if (str.length() != 0) {
System.out.println("Sending " + str);
Message.BroadcastMessage(str, sockets);
}
} catch (IOException ie) {
System.out.println("Connection lost: " + socch);
sockets.remove(socch);
socch.close();
} catch (ClassNotFoundException cnfe) {
System.out.println(cnfe);
sockets.remove(socch);
socch.close();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
}
} catch (IOException ie) {
ie.printStackTrace();
}
}

public static void main(String args[]) throws Exception {
int port = 12769;
new PollingChatServer(port);
}
}
 
E

Esmond Pitt

Joseph said:
Technically there are not non blocking socket write methods in any
language. There is either room enough in the socket write MCB to hold
the data, allowing the method to return, or there is not enough room,
and an error is returned to indicate a failure.

Technically and more accurately, there *are indeed* non-blocking socket
write methods in both C and Java. In non-blocking mode, a socket write
will put as much as it can of the application data into the socket send
buffer without blocking and return that count, which can be zero if
there was no room. This is not an error condition.

I don't know what is meant by 'MCB', it is not a term associated with
sockets.
Either increase your transmit buffer size, which I believe defaults to
32kb

The default is platform dependent. It is 8k on Windows which is not
sufficient.
, or find out why the data is not being transmitted to the network.

to which the answer can really only be that the client isn't reading
fast enough, or at all.
 
J

Joseph Dionne

Esmond said:
Technically and more accurately, there *are indeed* non-blocking socket
write methods in both C and Java. In non-blocking mode, a socket write
will put as much as it can of the application data into the socket send
buffer without blocking and return that count, which can be zero if
there was no room. This is not an error condition.

I don't know what is meant by 'MCB', it is not a term associated with
sockets.



The default is platform dependent. It is 8k on Windows which is not
sufficient.



to which the answer can really only be that the client isn't reading
fast enough, or at all.

One can read a socket non blocked, using a single method call, receiving
either data, or no data. But, one cannot code a single method call to
write non blocked in a "fire and forget" manner. Even you acknowledge
that write might fail to emit all the data one attempted to write. So,
one always needs to put a loop around socket write methods, terminating
only after all data has been emitted.

That is why is said "technically". Conceptually, a non blocked socket
read method is expected to do one of two things, return data, or
indicate that no data is returned, while a socket write can have three
states, all data written, some data written, no data written. Since
"some data written" will a application error. I'm pretty sure no one
desires half of the STREAM delivered to the remote client.
 
Ad

Advertisements

E

Esmond Pitt

Joseph said:
One can read a socket non blocked, using a single method call, receiving
either data, or no data.

or some data. There is a third state.
But, one cannot code a single method call to
write non blocked in a "fire and forget" manner. Even you acknowledge
that write might fail to emit all the data one attempted to write. So,
one always needs to put a loop around socket write methods, terminating
only after all data has been emitted.

or when you have something better to do in non-blocking mode than wait
for the client to empty his receive buffer. Also, at some point you want
to decide that this is never going to happen and you prefer to give up.
That is why is said "technically". Conceptually, a non blocked socket
read method is expected to do one of two things, return data, or
indicate that no data is returned, while a socket write can have three
states, all data written, some data written, no data written. Since
"some data written" will a application error. I'm pretty sure no one
desires half of the STREAM delivered to the remote client.

Nevertheless that is how both the non-blocking read and non-blocking
write calls behave on a socket. There are three states in both, and
technically your statement does not hold water.

and BTW what exactly is a socket MCB?
 
J

Joseph Dionne

Esmond said:
or some data. There is a third state.

Only proxy like applications, providing connectivity between two end
points, can truly read a socket STREAM without regard to message
boundaries. At some point, even a socket read method requires a
complete packet delivery.

As you may or may not know, not knowing the level of expertise you bring
to this discussion, socket stream of non ASCII STREAMS, use two to four
bytes preceding the data allowing the received to know the message size
and prepare applications to receive the data. Prior to threading
support, a relatively new feature, applications ip applications were
just state engines, with socket I/O just one state, using select() or
poll() to monitor state. These functions measured the leading edge
event of a socket STREAM, data has arrived. If one did not read all the
data received, select() (always), and poll() (most implementations)
would not signal the socket handle ready until more data arrives. This
is a common error in socket I/O applications.

My original point what that there exist no single socket interface
method that removes the responsibility to manage the socket STREAMS like
garbage collection has done for memory management. And, now we have
learned, even garbage collectors do not completely remove the job of
proper memory management, one can still obfuscate Object references in
many ways that prevent Object memory reclamation.
or when you have something better to do in non-blocking mode than wait
for the client to empty his receive buffer. Also, at some point you want
to decide that this is never going to happen and you prefer to give up.



Nevertheless that is how both the non-blocking read and non-blocking
write calls behave on a socket. There are three states in both, and
technically your statement does not hold water.

and BTW what exactly is a socket MCB?

An MCB, or the memory control blocks defining the socket's mbufs within
the ip stack application interface. It is a term I use, but is not part
of any user level, or even stack level, data structures. I was
incorrect to inject my nomenclature, but I have been working at low
level IP for decades, developing many features for my old IPX used with
such ease as Java's socket interfaces today.

Has that answered your question?
 
E

Esmond Pitt

Joseph said:
As you may or may not know, not knowing the level of expertise you bring
to this discussion, socket stream of non ASCII STREAMS, use two to four
bytes preceding the data allowing the received to know the message size
and prepare applications to receive the data.

I've only been doing sockets since BSD 4.1, about 1983-4, but if this is
supposed to be a statement that is true of all non ASCII streams it just
isn't. Some application protocols do it. Some application protocols e.g.
XDR do something else. TCP doesn't do *anything* except put the required
length field in the IP header. Quite a few application protocols don't
prefix message lengths either: Telnet, FTP, and HTTP for starters.
My original point what that there exist no single socket interface
method that removes the responsibility to manage the socket STREAMS like
garbage collection has done for memory management.

Well, I though your original point was 'Technically there are not non
blocking socket write methods in any language. There is either room
enough in the socket write MCB to hold the data, allowing the method to
return, or there is not enough room, and an error is returned to
indicate a failure.' There's now so much irrelevance being added such as
lectures on threads and further incorrect claims that the orignal
incorrect statement is being obscured, but it's still incorrect.
 
J

Joseph Dionne

Esmond said:
I've only been doing sockets since BSD 4.1, about 1983-4, but if this is
supposed to be a statement that is true of all non ASCII streams it just
isn't. Some application protocols do it. Some application protocols e.g.
XDR do something else. TCP doesn't do *anything* except put the required
length field in the IP header. Quite a few application protocols don't
prefix message lengths either: Telnet, FTP, and HTTP for starters.

And how are you able to access the length field from the IP header via a
socket?
Well, I though your original point was 'Technically there are not non
blocking socket write methods in any language. There is either room
enough in the socket write MCB to hold the data, allowing the method to
return, or there is not enough room, and an error is returned to
indicate a failure.' There's now so much irrelevance being added such as
lectures on threads and further incorrect claims that the orignal
incorrect statement is being obscured, but it's still incorrect.

Well, sir, I question your
 
E

Esmond Pitt

Joseph said:
And how are you able to access the length field from the IP header via a
socket?

You can't, and I haven't stated otherwise.
Well, sir, I question your

You question my what? Whatever this was going to be, I probably agree
with what you are trying say about how to program TCP streams, but
introducing all these inaccurate irrelevancies into the discussion isn't
helpful and causes confusion to uninformed readers.
 
Ad

Advertisements

J

Joseph Dionne

Esmond said:
You can't, and I haven't stated otherwise.



You question my what? Whatever this was going to be, I probably agree
with what you are trying say about how to program TCP streams, but
introducing all these inaccurate irrelevancies into the discussion isn't
helpful and causes confusion to uninformed readers.

My apologies, it was not my intention to send that message. Honoring
your concern of "inaccurate irrelevancies," I will not post replies
anymore, adding to the "confusion to uninformed readers."
 
M

Marcin Grunwald

Sameer said:
The methods writeObject and readObject of socket class are blocking
one. i.e. if we create a ObjectInputStream object using
new ObjectInputStream(socket.getInputStream()), the methods blocks
until it gets some stream stuff.
What is the corresponding non-blocking mthod so as to include in
non-blocking programming?

Maybe something like this:

byte[] buffer = new byte[xxxx];
(use NIO to non-blocking read whole stream and write it to buffer)
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
ObjectInputStream ois = new ObjectInputStream(bais);

Unfortunately you can call "new ObjectInputStream()" after you read whole
data from socket.
 
J

John C. Bollinger

Sameer said:
I have designed one chatting software using non-blocking features of
java.
In this project I transferred data using non-blocking methods of Buffer
related classes.

OK, that sounds reasonable.
Now I decided to change the design of the projct and I like to send the
data as objects over the network using readObject and writeObject
methods of socket class.

Why? What is to be gained by doing this, especially when you already
have a working program?
For this purpose, I have to create instances ObjectInputStream and
ObjectOutputStream.
As per our previous discussion on this group the constructors of these
classes are BLOCKING methods.

And what you have apparently missed is that reading and writing objects
are *necessarily* *also* blocking operations.
Then how to carry out this? Is there any alternative or I have to
continue with blocking approach i.e. a multithreaded chatting server
where each thread handles one connection?

My recommendation would be to forget about transferring objects, as I
don't see anything to be gained by it in your application. A
multithreaded server with blocking I/O is another alternative.
Depending on the nature of the task, a multithreaded server with
_nonblocking_ I/O is sometimes appropriate. That last is the only mode
I see in which you could manage to combine object I/O via Java's built
in mechanism with non-blocking I/O, but by the time you were done you'd
have much more complicated code than necessary, yet little or no
improvement over the blocking I/O scenario.
The code given under is not working...

I should say not. The only thing you do in a non-blocking manner is
accept connections. Even that you do a bit strangely, allowing the loop
to spin until it accepts the first connection. You then apparently
expect every live connection to provide a Message at every iteration of
the loop -- that's completely contrary to a non-blocking paradigm. I
cannot say how non-blocking-ready Message.BroadcastMessage may be, but
based on its apparent purpose, it doesn't appear to have any chance of a
correctly non-blocking implementation. Oh, and you don't seem to
provide any way to close a connection once it is opened.
Please suggest some remedy.

Learn how to correctly implement non-blocking I/O. You said you already
had a program that successfully used it, but your code below makes me
doubtful of that. Once you understand non-blocking I/O better,
contemplate Object I/O until you understand why it is incompatible with
non-blocking I/O (if you can't figure it out then go back to step 1).
Finally, use your new knowledge to redesign your application.

We're still here if you conceive specific questions along your path to
enlightenment, but if you come back with code that doesn't use a
Selector then I, for one, will not hear you.
 
S

Sameer

Dear Sir,
Thanks for responding to my post.
Posted is the most-simplified version of my original program.
My program is based on the source code for non-blocking chat server
provided in Advanced NIO, Manning Publication by Gregory Travis.
I have a working system. But in this system I have to do a lot of
string manipulation for managing the chat system.
I have to give code to each message send to client/server and then
decode it to display it appropriately.
If the message the wrapped in a object along with other relevant
information as fields and then this object is send, then the code will
be much simplified.
It is not possible to do 'Object Sending + NIO functionality'
simultaneously???
It seems that you have lot of doubts about the source code provided. If
you have some source code which explain efficient handling of NIO for
chat related stuff, please provide it to me.
-Sameer
 
S

Sameer

A lot of technical stuff here about my posting.

Can anybody provide some simple working examples about 'Object Sending
+ NIO functionality' in a Chat Server application?
 
Ad

Advertisements

J

John C. Bollinger

Sameer said:
It is not possible to do 'Object Sending + NIO functionality'
simultaneously???

Given the context of this thread, I'll take that as "It is not possible
to send and receive Objects without blocking???"

One last time: no, it is not possible.

Fuller explanation:

* Sending an object down a byte stream has two steps, (1) creating a
byte sequence representing the Object and all the other Objects it
refers to directly or indirectly, and (2) sending the bytes.
ObjectOutputStream bundles all this up into its writeObject() method.

* Receiving an object from a byte stream has two steps, (1) receiving
all the bytes for the Object itself and for all the other objects it
refers to directly or indirectly, and (2) assembling the objects.
ObjectInputStream bundles all this up into its readObject() method.

* It is a fundamental characteristic of nonblocking I/O that the number
of bytes transferred in a single operation is unpredictable; to send
some fixed number of bytes you need to queue them and repeatedly,
whenever the output channel is ready to accept some, send as many as you
can without blocking. To receive bytes you do much the opposite,
reading as many bytes as are available whenever any are available, and
buffering them or queuing them for further handling by the application.
There is typically a delay between the time one non-blocking
operation is dispatched and the time another one can be successfully
performed (with more than zero bytes transferred). All of that
(including both writing and reading for multiple channels) can be
managed in a single thread if it is done correctly.

It is possible to handle an object write without blocking by capturing
the output to a buffer (possibly by using a ByteArrayOutputStream) and
then enqueuing the contents of the buffer and sending them in a
non-blocking manner as described above. This is broken with respect to
preserving referential integrity across the network link (which requires
use of a single, continuous stream of objects, whereas this scheme would
need to use a separate stream for each top-level object), but it could
conceivably serve your purpose.

It is *not* possible to perform an object read across a network (or from
disk) without the possibility of blocking. This is because you need to
receive *all* the bytes of the object before you can reconstitute it.
At a low level you could conceivably use non-blocking I/O to get the
bytes, but the overall "read object" operation cannot ever be guaranteed
to complete without blocking because you are never guaranteed to get all
the bytes in one read. Depending on the number of bytes required and
the size of the various buffers involved, it might not be possible to
*ever* get all the bytes in one read. Note also that with that being
the case, your server would need to be multithreaded in any case -- the
(nonblocking) network I/O operations would need to run in their own thread.
 
J

John C. Bollinger

Sameer said:
My program is based on the source code for non-blocking chat server
provided in Advanced NIO, Manning Publication by Gregory Travis.

I am not familiar with the book, but the fact that a code appears in
print does not ensure that it is correct or bug-free. Moreover, if your
code does not exactly duplicate the published one then whether or not
the original code is correct is moot.
I have a working system.

No doubt it works, at least inasmuch as you can tell in your testing and
use of it. That does not necessarily imply that it is actually avoiding
ever blocking on I/O, however, or that it is correctly using the
non-blocking capabilities or other features of NIO correctly. The code
you posted definitely is missing some of the *essentials* of correct
non-blocking I/O.
But in this system I have to do a lot of
string manipulation for managing the chat system.
I have to give code to each message send to client/server and then
decode it to display it appropriately.

I'm not sure I understand. Are you talking about character encodings?
And where are you worrying about displaying the data? Are you in
control of the clients? If so, then simply ensure that the clients
always use the same charset (as each other) for sending and receiving
messages. UTF-8 (or possibly UTF-16) will handle any and all characters
Java supports. The server then never needs to decode (or recode) the
messages.
If the message the wrapped in a object along with other relevant
information as fields and then this object is send, then the code will
be much simplified.

I suspect the code could be much simplified via other approaches as
well. At some level, however, you have to recognize that a multi-user
network service is complex, and there's only so much simplification that
can be done.

Transferring data in object form might indeed be a good approach, but
you have to use standard, blocking I/O at the object level.
It seems that you have lot of doubts about the source code provided. If
you have some source code which explain efficient handling of NIO for
chat related stuff, please provide it to me.

I do not have such code (specifically for chat), though I have general
experience with NIO, and more with the equivalent features of C/UNIX. I
don't see any particular reason why your problem domain (chat service)
is relevant to the general use of NIO features or, specifically,
non-blocking I/O. The topic is sufficiently complex, however, that I am
not inclined to prepare an example code for you. I, or others here,
will likely be willing to critique *complete* codes.
 
J

jmricker

I would like to somehow interject my question into this discussion. I
also am writing a client/server using non blocking io. However I have
set up a selector to select those clients with buffers ready to be
read. Instead of using objects, I'm sending buffers of bytes. My
buffers are set up as:

[int id][int id2][int payload size][ payload of bytes of size
length ]

Now lets say my client has sent off two of these buffers as two
seperate (blocking?) writes in the time it takes for my server to get
around to readying from it. Are you saying that a blocking read will
just get the first buffer?

So far what I've been doing is this:

When a client connects, register the channel with a reading selector
with an object that wraps up a bytebuffer and does other administrative
tasks like checking header completeness.

When I select channels that I can read from, I read up to 512 bytes,
and push it into the container attached to the channel. I then check it
for completeness. If not, then I go off checking other channels, then
come back to this one, read off another 512 bytes, etc. Once I have a
complete header and payload, I pass it off the appropriate controller,
reset the container, and continue on.

I'm hoping to avoid the loop spending too much time reading in from one
client. My concern here is here, how can I be sure where the end of
the buffer is at? Lets say the client sends an incorrect payload size
or a byte of the payload gets lost in the transmission. If I have two
buffers sitting to be read, I could easily start reading bytes from the
second buffer into the first buffer. Any thoughts on my process?

Thanks
Joel
 
Ad

Advertisements

J

John C. Bollinger

jmricker said:
I would like to somehow interject my question into this discussion. I
also am writing a client/server using non blocking io. However I have
set up a selector to select those clients with buffers ready to be
read. Instead of using objects, I'm sending buffers of bytes. My
buffers are set up as:

[int id][int id2][int payload size][ payload of bytes of size
length ]

Now lets say my client has sent off two of these buffers as two
seperate (blocking?) writes in the time it takes for my server to get
around to readying from it. Are you saying that a blocking read will
just get the first buffer?

No, I'm not saying that. A single blocking read will get some number of
bytes, which may be anything from a single byte to the full contents of
both buffers (subject to various constraints, such as hardware and O/S
buffer sizes).
So far what I've been doing is this:

When a client connects, register the channel with a reading selector
with an object that wraps up a bytebuffer and does other administrative
tasks like checking header completeness.

When I select channels that I can read from, I read up to 512 bytes,
and push it into the container attached to the channel. I then check it
for completeness. If not, then I go off checking other channels, then
come back to this one, read off another 512 bytes, etc. Once I have a
complete header and payload, I pass it off the appropriate controller,
reset the container, and continue on.

That sounds like the right way to go about it, although you need to be
prepared for the case where you get the end one block _plus_ part or all
of another in the same read. If the client is sending data rapidly then
this is not too unlikely to happen.
I'm hoping to avoid the loop spending too much time reading in from one
client. My concern here is here, how can I be sure where the end of
the buffer is at? Lets say the client sends an incorrect payload size
or a byte of the payload gets lost in the transmission. If I have two
buffers sitting to be read, I could easily start reading bytes from the
second buffer into the first buffer. Any thoughts on my process?

TCP provides reliable transmission. It's not foolproof, but you don't
generally have to worry about data being lost in transmission without
the connection being broken altogether. (It would take a combination of
errors that is so unlikely to occur that you might as well ignore the
possibility.) Likewise accidental data corruption on the wire. On the
other hand, you either have to trust the client or have some way to
detect when it goes goofy. Your protocol does not seem to support the
latter.

I don't think any of that has much to do with hanging while reading from
any particular client. If a channel is ready to read then you can read
some number of bytes from it without blocking -- that's what it means
for the channel to be ready. You can use a blocking or nonblocking read
in this case; it doesn't matter. The alternative is to assign a unique
thread to each client, use blocking I/O, and get on with the rest of the
application. There are a great many servers that take the latter approach.
 
Ad

Advertisements


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

Top