> 1. If I have a buffer of size of 1024, and a client send me a first
> message how I know when finish the this first message because maybe
> he/she can send more messages. Each time the client send messages, they
> migth arrive together?

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
>> 1. If I have a buffer of size of 1024, and a client send me a first
>>message how I know when finish the this first message because maybe
[quoted text clipped - 10 lines]
> message
> - send only fixed length messages
I have found it easiest to use a terminator byte (#0 NULL for example)
at the end of message packet. If you send string data NULL should be
fine, but sending a binary files it might not work. Binary file may have
a terminator byte as a data byte. I have done only string-based messages
so it has not been a problem yet.
Basicly what I do is this:
* each connection has a private incomingBuffer ByteArrayOutputStream
* I put all incoming bytes to incomingBuffer
* I analyze buffer data during writing and look for NULL terminator
* if terminator is found I take bytes from startOfBuffer to terminator
byte and create a new message object
* message object is added to FIFO taskhandler queue
* all remaining incomingBuffer bytes stays in a buffer until next
terminator byte is found
To make life easier do not overuse threads. Keep most if not all NIO
handling code in a single thread. This will eliminate many nio bugs for
free. You may use a separate thread for message handler, that removes
messages from synchronized fifo queue.
Handling a response writes is another big task. I keep it in a nio
thread as well. Each connection has a private outgoingMessages list. nio
thread takes pending outgoing messages and writes data to the socket.
Christiansem - 21 Nov 2005 15:16 GMT
thanks folks for your ideas. I'm really glad
I found some code for read from a socketchanel and I would like what
is your opinion about it.
**************** First one ****************
http://www2.sys-con.com/ITSG/virtualcd/Java/archives/0705/schreiber/index.html
//requestLineBuffer is a ByteBuffer
public void readRequest() throws IOException {
try {
if (!requestLineBuffer.hasRemaining()) {
setError(414, "Request URI too long.");
prepareForResponse();
return;
}
socketChannel.read(requestLineBuffer);
if (!isRequestLineRead()) {
return;
}
requestLineBuffer.flip();
byte[] b = new byte[endOfLineIndex];
requestLineBuffer.get(b);
String requestline = new String(b, 0);
StringTokenizer st
= new StringTokenizer(requestline, " \r\n");
String method = st.nextToken();
uri = st.nextToken();
File file = new File(uri.substring(1));
if (st.hasMoreTokens()) {
protocol = st.nextToken();
}
if (!method.equals("GET")) {
setError(405, "Method " + method
+ " is not supported.");
} else if (!file.exists() || file.isDirectory()) {
setError(404, "Resource " + uri
+ " was not found.");
} else if (!file.canRead()) {
setError(403, "Forbidden: " + uri);
} else {
fileLength = file.length();
fileChannel
= new FileInputStream(file).getChannel();
}
prepareForResponse();
} catch (NoSuchElementException nsee) {
// we didn't read enough tokens
setError(400, "Bad request.");
} catch (Exception e) {
// something else went wrong
setError(500, "Internal Server Error.");
prepareForResponse();
e.printStackTrace();
}
**************** Second one ****************
http://www.onjava.com/pub/a/onjava/2004/09/01/nio.html?page=3
/**
* Holds a message that is not fully assembled. This buffer is
fixed-size.
* If it is exceed, an Exception is raised by the decode() method.
*/
private byte[] buffer = new byte[BUFFER_SIZE];
/** Write position on the previous buffer. */
private int pos = 0;
public ByteBuffer decode(ByteBuffer socketBuffer) throws IOException
{
// Reads until the buffer is empty or until a packet
// is fully reassembled.
while (socketBuffer.hasRemaining()) {
// Copies into the temporary buffer
byte b = socketBuffer.get();
try {
buffer[pos] = b;
} catch (IndexOutOfBoundsException e) {
// The buffer has a fixed limit. If this limit is reached, them
// most likely the packet that is being read is corrupt.
e.printStackTrace();
throw new IOException(
"Packet too big. Maximum size allowed: " + BUFFER_SIZE + "
bytes.");
}
pos++;
// Check if it is the final byte of a packet.
if (b == ETX) {
// The current packet is fully reassembled. Return it
byte[] newBuffer = new byte[pos];
System.arraycopy(buffer, 0, newBuffer, 0, pos);
ByteBuffer packetBuffer = ByteBuffer.wrap(newBuffer);
pos = 0;
return packetBuffer;
}
}
// No packet was reassembled. There is not enough data. Wait
// for more data to arrive.
return null;
}
In which of them I could base my producction application, I mean which
is the better option for read from a bytebuffer in nonbloking IO for a
producction application.
Thanks a lot for your time
Bye
PD again sorry for my english.