Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Yet another NIO networking API  (Read 2127 times)
0 Members and 1 Guest are viewing this topic.
Offline otelo

Junior Member





« Posted 2006-06-30 13:48:16 »

well, how to justify this topic, let's see...

there have been many NIO servers written and posted as examples on this board and elsewhere, but since so few of them included a NIO client, I decided to write my own.
I tried to keep the networking part as simple as possible, so what you basically get here is one server class, one client class and a listener interface to handle message arrival and reports. both, server and client have their own inbox, which you poll to retrieve received messages.

I included a simple program, that uses a server to synchronize it's clients. please have a look and share your hate.

link << It actually works since 01 July 2006.
Offline otelo

Junior Member





« Reply #1 - Posted 2006-06-30 21:48:22 »

best thing is, now I'm getting weird behaviour with the test app on my home computer, which I'm unable to reproduce on my work computer (where I wrote it).

moving the little thingies in a client too fast sends frequent network updates which causes something to break and the server hogs the cpu. how do you guys debug this networking stuff anyhow?
Offline sunsett

Senior Member




ribbit!


« Reply #2 - Posted 2006-06-30 22:44:09 »

hehe, debugging networking can definitely be a pain to mess with...particularly NIO stuff as I'm learning can be quite a beast to work with.

Just out of curiosity did you happen to look at http://javagamenetworking.dev.java.net in your searching?  It provides very nice Client/Server features and should be about as simple as is possible without losing capabilities.  I'm actually about to release version 2.0 which has some significant improvements and quite a bit of help from Riven setting me straight on my mistakes on NIO. :-p

I'll take a look at your API and if something jumps out at me.

-Matt Hicks
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline DanK

Junior Member




Javver games rock yawel!


« Reply #3 - Posted 2006-07-01 03:38:15 »

I haven't looked at your code so this might be obvious to you, but have you made sure you are turning off write ops afer you are done writing (or aren't trying to write data)? There are a few posts in these forums about that particular issue

Offline otelo

Junior Member





« Reply #4 - Posted 2006-07-01 08:37:10 »

Quote from: sunsett
I'm actually about to release version 2.0 which has some significant improvements and quite a bit of help from Riven setting me straight on my mistakes on NIO. :-p

I'll take a look at your API and if something jumps out at me.

yes, I took a look at your code but it's rather an overkill for my needs. simplicity in function and implementation is my personal goal with this one. pure TCP/IP reliable message delivery with a couple of method calls, basically to demonstrate the core functionality of NIO and make it work.

I also remember from another thread how Riven showed up and proclaimed your code to be buggy with some very obvious errors in it. just to mention an example, I'm using unsynchronized LinkedList-s in a very obvious manner for the sole reason that I'd love to be publicly chastised by Riven also. :-)  what could go wrong with an unsynchronized LinkedList other than a poll returning null while another thread is adding an object? my code should be able to handle that but I'll take a look at it today and synchronize them all.

if it's something with the NIO stuff, than I'm kind of lost because it works, it just breaks very unpredictably.

Quote from: sunsett
I haven't looked at your code so this might be obvious to you, but have you made sure you are turning off write ops afer you are done writing (or aren't trying to write data)? There are a few posts in these forums about that particular issue

believe me, I've read all those threads and then some more. you could take a look at the code, it's very short! (and it's Saturday) .

...you bring up a point though, because turning off write ops depends on one of those unsynchronized LinkedList accesse's return value, so I should have considered that a clue earlier.

Update: so I'm using Vector for now.  link
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 743
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #5 - Posted 2006-07-01 11:08:52 »

Hm, there goes my reputation of fighting for worldpeace and what-not.


In NIOSession.doRead(...)

I found this piece of code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
        if (readState == 1)
        {
            if ((bytesLast = this.channel.read(bBuffer)) < 0) throw new IOException("ioe");
            else if ((bytesRead += bytesLast) == msgLength)
            {
                byte[] msgBody = new byte[msgLength];
                bBuffer.flip();
                bBuffer.get(msgBody);
                bBuffer.clear();
                readState = 0;
                bytesRead = 0;
                inbox.add(new NIOMessage(msgBody, selKey));
                listener.handleNIOMsg();
            }
        }


The problem here is that you might have received part of the *next* message too, in which case this is the case:

1  
(bytesRead += bytesLast) > msgLength


To ensure you read-back the correct amount of bytes in your ByteBuffer, use something like this code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
if((bytesRead += bytesLast) > msgLength)
{
     byte[] msgBody = new byte[msgLength];

     // set 'range' to current message
     bb.position(0);
     bb.limit(msgLength);
     bb.get(msgBody);

     // set 'range' to pending bytes
     bb.position(msgLength);
     bb.limit(bytesRead);
     bb.compact();
}



I have to warn you though that the above code is not very efficient, but it will be fast enough for almost anything (will probably go over a few MB/s)

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 743
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #6 - Posted 2006-07-01 11:18:10 »

And now a bug related to multi-threading:

1  
2  
3  
4  
5  
6  
7  
8  
9  
            if (outbox.size() == 0)
            {
                ...
            }
            else
            {
                wBuffer[1] = outbox.remove(0);
                ...
            }


This code is not thread-safe! You seem to assume the outbox-size is not 0 when you arrive in the else-block. In reality another Thread might have snatched the object in between those two calls. The fact that Vector is synchronized is completely irrelevant, as the lock/monitor is lost between those calls. You'll have to manually synchronize the two invocations.

Update:
On second thought it is unlikely that more than 1 thread accesses the doWrite method, so the problems you're finding have nothing to do with this one.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline otelo

Junior Member





« Reply #7 - Posted 2006-07-01 15:05:54 »

Praised Be The Riven!

seriously, thanks for the swift reply. guess what, you were right! best thing is I found an elegant solution right away. take a look:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
        if (readState == 0)
        {
            if ((bytesLast = this.channel.read(lBuffer)) < 0) throw new IOException("ioe");
            else if ((bytesRead += bytesLast) == 2)
            {
                msgLength = lBuffer.getShort(0);
                lBuffer.clear();
                bBuffer.clear();
                bBuffer.limit(msgLength);
                readState = 1;
                bytesRead = 0;
            }
        }
       
        if (readState == 1)
        {
            if ((bytesLast = this.channel.read(bBuffer)) < 0) throw new IOException("ioe");
            else if ((bytesRead += bytesLast) == msgLength)
            {
                byte[] msgBody = new byte[msgLength];
                bBuffer.flip();
                bBuffer.get(msgBody);               
                readState = 0;
                bytesRead = 0;
                inbox.add(new NIOMessage(msgBody, selKey));
                listener.handleNIOMsg();
            }
        }


I just set the body Buffer's limit on the fly before each read. it might not be too effective performance-wise if the messages come in small chunks, but that's just a design decision which can be taken into consideration when assembling messages.

you are right, the MT-related bug you described shouldn't be a bug really, because only the selector thread removes messages from the outbox. the worst that could happen is that the selector thread deletes the write ops just after another thread inserted a message to the outbox and set the channels key as writable. that's very unlikely to occur and even if, it would get remedied with the next messasge inserted for sending.

I have updated all the links to the now hopefuly working code.  thanks again.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (24 views)
2014-07-24 01:59:36

Riven (22 views)
2014-07-23 21:16:32

Riven (18 views)
2014-07-23 21:07:15

Riven (21 views)
2014-07-23 20:56:16

ctomni231 (49 views)
2014-07-18 06:55:21

Zero Volt (45 views)
2014-07-17 23:47:54

danieldean (36 views)
2014-07-17 23:41:23

MustardPeter (39 views)
2014-07-16 23:30:00

Cero (54 views)
2014-07-16 00:42:17

Riven (54 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!