Using the WrappedOutputStream and WrappedInputStream classes (from the 
samples.socket.io package of Xerces) for the transport of XML documents between 
a client and a server, we recently became aware of the following problem with 
the WrappedOutputStream class:

   It is currently only possible to send XML documents
   whose byte[] representation doesn't exceed 65535 bytes
   using the write(byte[] b,int offset,int length) method. 

As I see it, this is caused by a combination of the particular method 
implementation and the fact that the protocol used by these classes represents 
the size of each byte[] "packet" by a short, i.e. 16 bits.


There are several ways one can fix/circumvent this problem of course, some of 
which are:

1) Introduce a loop, and use WrappedOutputStream's write(int b) method instead 
of the write(byte[] b, int offset, int length) method. The write(int b) method 
buffers the bytes in an internal byte[] array which is 1024 bytes long (by 
default), and sends a 1024 byte packet each time the buffer is filled up. 
 
2) One could modify the write(byte[] b, int offset, int length) method so that 
it chunks the byte[] argument into several smaller pieces, each less than 65535 
bytes long, and sends these as separate packets.

3) One could modify the WrappedOutputStream/WrappedInputStream classes so that 
they use a long (64 bits) instead of a short to represents the size of each 
byte[] packet.


I tried approach 1) first, replacing

    wrap_os.write(bytes, 0, bytes.length);

by

    for(int i=0; i<bytes.length; i++) {
        wrap_os.write(bytes[i]);
    }

in my code, where wrap_os is a WrappedOutputStream object. This failed, and 
revealed a bug in the write(int b) method in WrappedOutputStream:

[snippet from WrappedOutputStream.java]

    /** 
     * Writes a single byte to the output. 
     * <p>
     * <strong>Note:</strong> Single bytes written to the output stream
     * will be buffered
     */
    public void write(int b) throws IOException {
        fBuffer[fPosition++] = (byte)b;
        if (fPosition == fBuffer.length) {
            fPosition = 0;
            fDataOutputStream.writeShort(fBuffer.length);  <------- 
            write(fBuffer, 0, fBuffer.length);
        }
    } // write(int)

    /** Writes an array of bytes to the output. */
    public void write(byte[] b, int offset, int length) 
        throws IOException {

        // flush existing buffer
        if (fPosition > 0) {
            flush0();
        }

        // write header followed by actual bytes
        fDataOutputStream.writeShort(length);
        super.out.write(b, offset, length);

    } // write(byte[])



When fBuffer is filled up, the size of the buffer is written as a short onto 
the DataOutputStream, and then the fBuffer is written using the write(byte[] b, 
int offset, int length) which also writes the size of the buffer onto the 
DataOutputStream before writing the actual byte array. This makes the 
WrappedInputStream object at the receiving end somewhat confused... This is 
easily fixed by deleting the fDataOutputStream.writeShort(fBuffer.length); line 
from the write(int b) method.


Anyhow, I guess I will have to do something along the lines of 2) or 3) above, 
since the WrappedOutputStream class currently doesn't handle large byte[] 
arrays as it seems. If anyone has experienced/dealt with the same problem, tips 
and comments are of course greatly appreciated.


--
------------------------------------------------
 Morten Bj�rhus
 TBS Communications, Messaging and Mobility
 [EMAIL PROTECTED],  tel: +47 41660525
------------------------------------------------


 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to