Updated network API

The New Dawn network API has been updated to use NIO. It’s lower level than herks headquarters engine, it just sucks up and spits out ‘Message’ objects across a TCP link. I’m still evaluating the benifits of UDP (yes i have read ‘The’ thread :)). When I get far enough along with darkvoid to make my own observations I will see if I can be bothered :).

Source, javadoc and an example app are included.

Comments and critisims are welcomed

Cheers

Endolf

[quote]It’s lower level than herks headquarters engine, it just sucks up and spits out ‘Message’ objects across a TCP link.
[/quote]
:slight_smile: … well, HeadQuarters package ‘objectbus’ does that as well and is also meant to be used on that level. So only some parts of HQ are high level (those that maintain a distributed state or implement a predefined service like chat or clock sync).

JPilots ‘I shot!’ messages are of that kind…

(is this already a shameless plug now?)

[quote](is this already a shameless plug now?)
[/quote]
Yes :), but we’ll let you off in return for the same later :slight_smile:

Endolf

what’s the url? I looked at http://www.newdawnsoftware.com/ but couldn’t see it.

Cheers,

Wil.

Hi
From the main site follow the links to resources, and Early Access Libraries.

HTH

Endolf

How is dark void coming along? Still using the API from the new dawn site for networking?

Hi Endolf and Kev,

I like your NIO API, its quite elegant and simple. I examined your code and ran my own tests and I noticed that the recieveMessage method would return null twice before it returned a message, even when I knew the message was waiting there. So I changed the method to this, and it works as it should:

public Message readMessage() throws IOException {
	int addBytes;

	if (invalid) {
		return null;
	}

	if (state == WAIT_FOR_CODE) {
		addBytes = channel.read(shortBuffer);

		if (addBytes < 0) {
			invalid = true;
			throw new IOException("Connection closed");
		}
		read += addBytes;

		if (read == 2) {
			messageCode = shortBuffer.getShort(0);
			shortBuffer.rewind();
			state = WAIT_FOR_LENGTH;
			read = 0;
		}
		//return null;
	} //else if (state == WAIT_FOR_LENGTH) {
	if (state == WAIT_FOR_LENGTH) {
		addBytes = channel.read(shortBuffer);

		if (addBytes < 0) {
			invalid = true;
			throw new IOException("Connection closed");
		}
		read += addBytes;

		if (read == 2) {
			messageLength = shortBuffer.getShort(0);
			bodyBuffer.limit(messageLength);
			shortBuffer.rewind();
			state = READING_BODY;
			read = 0;
		}

		//return null;
	} //else if (state == READING_BODY) {
	if (state == READING_BODY) {
		addBytes = channel.read(bodyBuffer);

		if (addBytes < 0) {
			invalid = true;
			throw new IOException("Connection closed");
		}
		read += addBytes;

		if (read == messageLength) {
			Message message = factory.getMessage(messageCode);
			if (message != null) {
				ByteArrayMessageEncoder.decode(message,bodyBuffer.array());
			}

			bodyBuffer.rewind();
			state = WAIT_FOR_CODE;
			read = 0;

			return message;
		}

		//return null;
	}
	return null;
}

Good idea?

Also, how hard would it be to adapt your library to UDP NIO?

Thanks,
Keith

Interesting API. I would submit that if you’re going to be having to encode and decode your messages yourself anyway you might as well just utilize Java’s built-in features directly. Of course there are some inherent structural benefits to being able to abstract explicit messages the way the API does.

My API is also based around Message objects, but removes the need for encoding and decoding utilizing dynamic introspection and creation. It’s definitely higher level than this though.

-Matt Hicks

Guys,

The last post from Endolf on this thread was 2004 - ND Net hasn’t been updated for the longest time - we’ve both moved away from it. I wouldn’t suggest getting dependent on it.

Kev

Sure. But, I hope you won’t mind if I use and modify your code…?

The API is extremely low-level, and that’s what’s appealing. It doesn’t really try do anything more than send a byte array and recieve the byte array as a whole on the other side. (I’ve slimmed the NewDawn code even further into 2 classes that just deal with byte arrays)

To do anything more than that then JGN or another network library would be great, but for ‘roll-your-own’ solutions (like my SS streams I suppose) then byte array send/recieve is all you want.

Keith

Incidently, this low level wrapping of byte arrays into arbitary messages pattern fits really nicely into the Project Darkstar world.

Kev

hi,

I consider myself a newb in the networking department, so please don’t feel insulted should I be pointing out problems that are no problems at all. :wink:

I was looking at the newdawn code and I have some questions concerning the ByteArrayMessageEncoder’s encode method. I’ll place my questions directly into the code block if you don’t mind:


 public static byte[] encode(Message message) throws IOException 
  {
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    
    DataOutputStream out = new DataOutputStream(bout);
    out.writeShort(message.getMessageCode());
    out.writeShort(0); // length
    message.encode(out);
    
    // considering you use a message structure of 
    //
    //  CODE[2B] - LENGTH[2B] - BODY[variable_length] ,
    //
    // should the next two lines not be commented out?
    
    out.writeShort(message.getMessageCode());
    out.writeShort(bout.size()-4); // length
    
    // while using the following bitwise manipulations
    // to correct the message's length in your byte[] ,
    // why not use integer for length with the rest of
    // the code untouched? you would achieve the 
    // equivalent of using an unsigned short increasing
    // the max length of your message from 32K to 64K,
    // which as Riven pointed out in another thread is 
    // considered a drawback. this would also need to be 
    // addressed in the Connection's readMessage / 
    // writeMessage methods of course but why not?
    // nnot very elegant I guess.
    //
    // also, why not include a
    //
    // public short getMessageLength(); 
    //
    // in your Message interface and let people handle this 
    // themselves?
    
    byte[] data = bout.toByteArray();
    short length = (short) (bout.size()-4);
    data[3] = (byte) (length & 0x00FF);
    data[2] = (byte) ((length & 0xFF00) >> 8);
    
    return data;
  }

Hi

It’s all code I’m no longer using, feel free to make any modifications you want :slight_smile:

Endolf

Ditto, I’ve tried to point this out above!

Kev