Non-blocking method for reading writing objects to sockets

Discussion in 'Java' started by Sameer, May 6, 2005.

  1. Sameer

    Sameer Guest

    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?
     
    Sameer, May 6, 2005
    #1
    1. Advertising

  2. Sameer wrote:
    > 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
     
    Joseph Dionne, May 6, 2005
    #2
    1. Advertising

  3. Sameer wrote:

    > 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.

    --
    John Bollinger
     
    John C. Bollinger, May 6, 2005
    #3
  4. Sameer

    Sameer Guest

    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);
    }
    }
     
    Sameer, May 7, 2005
    #4
  5. Sameer

    Esmond Pitt Guest

    Joseph Dionne wrote:
    >
    > 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.
     
    Esmond Pitt, May 7, 2005
    #5
  6. Esmond Pitt wrote:
    > Joseph Dionne wrote:
    >
    >>
    >> 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.


    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.
     
    Joseph Dionne, May 7, 2005
    #6
  7. Sameer

    Esmond Pitt Guest

    Joseph Dionne wrote:
    > 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?
     
    Esmond Pitt, May 8, 2005
    #7
  8. Esmond Pitt wrote:
    > Joseph Dionne wrote:
    >
    >> 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.


    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.

    >
    >> 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?


    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?
     
    Joseph Dionne, May 8, 2005
    #8
  9. Sameer

    Esmond Pitt Guest

    Joseph Dionne wrote:
    >
    > 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.
     
    Esmond Pitt, May 9, 2005
    #9
  10. Esmond Pitt wrote:
    > Joseph Dionne wrote:
    >
    >>
    >> 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.
    >


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

    > > 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.


    Well, sir, I question your
     
    Joseph Dionne, May 9, 2005
    #10
  11. Sameer

    Esmond Pitt Guest

    Joseph Dionne wrote:
    > 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.
     
    Esmond Pitt, May 9, 2005
    #11
  12. Esmond Pitt wrote:
    > Joseph Dionne wrote:
    >
    >> 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.
    >
    >


    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."
     
    Joseph Dionne, May 9, 2005
    #12
  13. Sameer wrote:

    > 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.

    --
    Cheers
    grundig
     
    Marcin Grunwald, May 9, 2005
    #13
  14. Sameer wrote:

    > 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.

    > 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();
    > }
    > }


    --
    John Bollinger
     
    John C. Bollinger, May 9, 2005
    #14
  15. Sameer

    Sameer Guest

    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
     
    Sameer, May 10, 2005
    #15
  16. Sameer

    Sameer Guest

    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?
     
    Sameer, May 10, 2005
    #16
  17. Sameer wrote:

    > 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.

    --
    John Bollinger
     
    John C. Bollinger, May 10, 2005
    #17
  18. Sameer wrote:

    > 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.

    --
    John Bollinger
     
    John C. Bollinger, May 10, 2005
    #18
  19. Sameer

    jmricker Guest

    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
     
    jmricker, May 11, 2005
    #19
  20. jmricker wrote:

    > 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.

    --
    John Bollinger
     
    John C. Bollinger, May 11, 2005
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hendra Gunawan
    Replies:
    1
    Views:
    12,756
    Allan Herriman
    Apr 8, 2004
  2. Andre Kelmanson

    blocking i/o vs. non blocking i/o (performance)

    Andre Kelmanson, Oct 10, 2003, in forum: C Programming
    Replies:
    3
    Views:
    960
    Valentin Tihomirov
    Oct 12, 2003
  3. nukleus
    Replies:
    14
    Views:
    851
    Chris Uppal
    Jan 22, 2007
  4. Christian
    Replies:
    5
    Views:
    748
    Esmond Pitt
    Dec 2, 2007
  5. Serge Savoie
    Replies:
    4
    Views:
    283
    Serge Savoie
    Oct 1, 2008
Loading...

Share This Page