Sign in to follow this  
Jacob_

[java] SocketChannel selector doesn't block

Recommended Posts

I'm having a problem with a game server I'm writing. I'm using a Selector, but when the client sends two packets quickly, it will be received as one key with one packet stuck on the end of the other. What's wrong?
            while(true)
            {
                sel.select();
                Set readyKeys = sel.selectedKeys();
                Iterator itr = readyKeys.iterator();
                while(itr.hasNext())
                {
                    SelectionKey key = (SelectionKey) itr.next();
                    itr.remove();
                    if(key.isReadable())
                    {
                        inputbuf.clear();
                        sc.read(inputbuf);
                        inputbuf.flip();
                        byte cmd = inputbuf.get();
                        outputbuf.clear();
                        //do something
                    }
                }
            }

Share this post


Link to post
Share on other sites
This is a feature, not a bug. Both of the packets were written to the byte buffer before you read from it. You'll need to modify your code so that it's guaranteed to read only one packet at a time, regardless of how many are in the byte buffer.

Share this post


Link to post
Share on other sites
Quote:
Original post by RobAU78
This is a feature, not a bug. Both of the packets were written to the byte buffer before you read from it. You'll need to modify your code so that it's guaranteed to read only one packet at a time, regardless of how many are in the byte buffer.


So would that mean iterating through all the bytes in the buffer and figuring out where a new packet starts, or is there a better way?

Share this post


Link to post
Share on other sites
(Assuming you're using TCP)

TCP is a stream protocol. This means it does not guarantee the preservation of 'boundaries' implicit when you attempt to send a given buffer at a time.

You need to have a framing protocol layered over the top of it. A simple solution is to prefix each packet of data with the packet length. You can then use this on the receiver's end to determine where packets should be delimited and split apart from the incoming TCP stream.

See Question 14 in the Multiplayer and Network Programming forum FAQ.

Share this post


Link to post
Share on other sites
Thanks for that, I never thought of TCP as being a stream protocol. This is actually a custom server for another game, so I can't edit the packets, but I'm guessing something like this should work, since each type of packet has a fixed length:

itr.remove();
if(key.isReadable())
{
inputbuf.clear();
sc.read(inputbuf);
inputbuf.flip();
while(inputbuf.remaining() > 0)
{
byte cmd = inputbuf.get();
//do some more get() calls based on what type of packet it is
}
}

(untested, I can't get to my code from here)

This is a bit offtopic, but I have another question. When 2 clients from the same IP are connected, is it possible that data meant for one might be sent to the other?

I've been testing with 2 clients and server on the same machine, and I noticed that about 50% of the time the 2nd client connects, it will not be spawned on the 1st client's screen, instead the 1st client will respawn itself back at the spawn point.

I've debugged a lot and the only thing I can think of is that the 1st client is receiving a spawn packet meant for the other. Is this possible?

Share this post


Link to post
Share on other sites
Quote:
Original post by Jacob_
Thanks for that, I never thought of TCP as being a stream protocol. This is actually a custom server for another game, so I can't edit the packets, but I'm guessing something like this should work, since each type of packet has a fixed length:

itr.remove();
if(key.isReadable())
{
inputbuf.clear();
sc.read(inputbuf);
inputbuf.flip();
while(inputbuf.remaining() > 0)
{
byte cmd = inputbuf.get();
//do some more get() calls based on what type of packet it is
}
}

(untested, I can't get to my code from here)

Sure, that's about the only way to do it in this case.

Quote:
This is a bit offtopic, but I have another question. When 2 clients from the same IP are connected, is it possible that data meant for one might be sent to the other?

I've been testing with 2 clients and server on the same machine, and I noticed that about 50% of the time the 2nd client connects, it will not be spawned on the 1st client's screen, instead the 1st client will respawn itself back at the spawn point.

I've debugged a lot and the only thing I can think of is that the 1st client is receiving a spawn packet meant for the other. Is this possible?


On the network stack side, no. Each TCP connection from a single machine will have a different port on the client side, allowing data to be routed to the correct application instance. Sounds like you're getting something mixed up in your application side, whether it be the network code, or perhaps something more game-specific related to spawning or something.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this