NIO Causes Filled Buffer

Hey guys, I’m running into a problem with JGN that I’m not really sure how to resolve. I’m using NIO for both TCP and UDP and it sends messages slightly faster than it can process them on the other side. Now in practicality bandwidth would be the limiting factor, but when you’re running on the same local machine for testing you’re able to send messages faster than they can be processed and the SocketChannel’s buffer is overflowing so packets are being lost. Is there any way to resolve this without blocking? Currently I am having to put delays into the sender in order to make it go at least as fast as the receiving end, but obviously I don’t want to do that in the long-run.

http://javagamenetworking.dev.java.net

-Matt Hicks

When using TCP this shouldn’t occur, as the sending end will just stop sending bytes, as it fills the ‘local’ sending-buffer too, which stops the OP_WRITE ‘events’ from the SelectionKey.

With UDP there is not much you can do, except delaying.

Note: if you do not use OP_WRITE you’re at the mercy of OS dependant wicked magic, according to blahblahblahh (iirc - pretty sure)

Perhaps I’m doing this wrong then:

SocketChannel channel = SocketChannel.open(new InetSocketAddress(....));
channel.configureBlocking(false);
ByteBuffer sendBuffer = ByteBuffer.allocate(512000);
sendBuffer.clear();
sendBuffer.put(bytes);
sendBuffer.flip();
channel.write(sendBuffer);

This is a simplified example, but should I be doing something in addition or alternatively to this?

Thanks,

Matt Hicks

Take a look at the javadocs of the SelectionKey class and the Selector class. All you every wanted to know about async NIO :slight_smile:

Will do…thanks for the tip…

-Matt Hicks

Matt, I’m using similar system as yours, just I have queue and add bytes to queue… for testing purposes it works and that’s why I didn’t change it to official, proper one.
Anyway as I understand (and will implement it in my game at one point) when you have some data to be written you need to register op write… write event will happen and there when you’re finished sending data you deregister op write. Shame there’s no documentation of this, just few simple examples of basic things.

Riven,

Want to be a developer on JGN? :-p

I originally created this project so I could just write a networking API so I wouldn’t have to think about networking when I’m writing games…boy was I ignorant. :-o

-Matt Hicks

My free time is so limited :slight_smile:

Yet I love designing non-trival (network) APIs…

I haven’t yet found what JGN is all about and how it is setup, so that’s probably what I’m going to do in the next 5 minutes

Update: where are the javadocs? I’d rather not browse through SVN pages.

While browsing through the source of the com.captiveimagination.jgn package (not the subs ATM) I see quite a few bugs and lots of inefficiencies. Explaining them would take longer than fixing them - get the hint? :slight_smile:

To name a bug:
InternalMessageListener.sendCertified(…) does not send anything when it is backed by a TCPMessageServer - it makes sense that it has to do less work, as TCP does the certification, but it has to send the data at least.

And a questionable design-choice:
You have to find the tcp-connection (involves creating the key -> creates a StringBuffer) in a hashtable for every packet you send/receive. This will reduce performance and is kinda hackery, as you have to pass the host and port each and everytime. You should at least (if you want to keep this design) put the host/port in 1 object, like InetSocketAddress (no need for the IP class at all)

There is also a serious bug in CustomByteArrayInputStream setting the wrong position if
read(buf, off, len)
is called and off != 0

(bugfix: position += len, instead of: position += len-off)

Sent you a message…I will get right on these. :o

Thanks a lot for the bug report. :wink:

-Matt Hicks