I am trying to write about 120kB of data through a TCP-connected socket. This data is divided into records that are each approximately 100B or so in size. The problem I'm running into is that somewhere about halfway through, my client gets out of sync and eventually crashes because of invalid size information on the records. after some experimentation, it seems to me that this behavior is what i might expect if there is a buffer (i'm not using bufferedoutputstream) that is being unpredictably overwritten before the queued bytes are being flushed through the stream to the client. i have tried calling flush() between each record, but that doesn't seem to have any effect on this. i'm not really seeing anything else in the javadocs that seems relevant. can anyone help me on this?

Basically, writing n bytes to a TCP stream does not mean that n bytes can be read. It is a stream.

I struggled with that myself when doing my NIO stuff, receiving messages partly or getting more than one a time. I solved that easily by truely following the 'stream' paradigma. Collecting data until a message is complete, placing the rest of the read into the next message buffer.

If I understand your question correctly, the answer is no. I only pull out a message if I have all of it's data; I do this by checking if there is enough data available(). This is what I'm using for that purpose:

/** * decodeMessage is called internally when there is data in the input stream */privatevoiddecodeIncomingMessages() {

if(!connected) return; // no need to mess with this nowtry {if(input.available() > 2) { // at least the size information and one more byteinput.mark(BUFFER_SIZE);intsize = input.readShort(); // message sizeif(input.available() < size) {input.reset(); // return to the mark; not enough data is availablereturn; }// System.out.println("size of incoming: " + size);ByteBufferbuffer = bufferPool.checkoutBuffer();input.read(buffer.array(), 0, size);buffer.mark(); // so we can go back to this point if it shouldn't be processed on this low levelshorttype = buffer.getShort();switch(type) { // check for low-level protocol messagescaseProtocol.DISCONNECT:try {socket.close(); } catch(Exceptione) {System.out.println("Error closing Session socket on Protocol.DISCONNECT."); }connected = false;bufferPool.checkinBuffer(buffer);break;caseProtocol.CONNECTED:connected = true;bufferPool.checkinBuffer(buffer);break;default: buffer.reset(); // return it to the point where the message type can be readenqueueIncomingMessage(buffer); // put this back on topbreak; } } }catch(IOExceptione) {e.printStackTrace();handleSessionError();return; } }

/** * sendMessage is called internally when flushing all queued messages to the output stream * @param message the message to be sent */privatevoidflushOutgoingMessages() {

Hm, hard to see. I'd feel a bit uncomfortable concerning input.mark()/reset() bc. they establishe states that easily might get shaken....

Maybe you could try to just plain read the socket to the end in a test environment, just to make sure wether the problem is on the sender or the receiver side?

Anyway, I provide a snippet of what I do. It different for I always read into my buffer succesivly until input is exhausted or the buffer it full. Than I evaluate it and separate the messages from it. If I reach the end of the buffer, I try to read further.This does not require to mix ByteBuffer and Socket actions.

//// Parse the buffer and make BusTickets from it.// Notify the listeners about what happened.// while ( mBuffer.position() < mBuffer.limit() ) {// Can we read at least one short completely? if ( mBuffer.remaining() < 2 ) { prepareBufferForNextRead(); return false; // --> LEAVE, we are NOT ready! }

// Retrieve length of the message. short ticketlen = mBuffer.getShort();

//// Is the following ticket completely in the buffer?// if ( ticketlen > mBuffer.remaining() ) {// Step back two byte to set reading position at the length-short again. mBuffer.position( mBuffer.position() - 2 ); prepareBufferForNextRead(); return false; // --> LEAVE, we are NOT ready! }

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org