Packet protocols (and other issues) for simple multi-user worlds

Hi, I’m currently developing a simple interactive multi-user world (for mainly chatting, and walking around exploring the world) in Java.

I’ve only 2 years of experience in Java and games programming in general, and this is my first project of its kind.

Anyway, I’ve implemented a Client/Server framework, which *technically" I can use for any generic networked application, but I plan to build my multi-user game world on top of this framework. It’s part of my computer science final project at university.

Anyway, I’ve mainly used guesswork to build the various parts of the client and server framework, i’ll list and describe them, just wondering how it compares to how things are done in a standard way. Any help and feedback would be much appreciated thanks…

The issues are:

  1. Packet protocols. I use bufferedwriter/reader to communicate between sockets, and the client and server sends packets to each other. The packet is structured as follows

a string consisting of:

 function code (byte), data1 (byte), data2 (string)

and there are single characters in between each of these elements to delimit them.

The function code describes the high-level function that is being sent to client/server, the data1 describes any data needed for that function, and data2 is a string of variable length, if required.

For example, the client sends a global chat command to the server as follows:

*7&0"Hello this is a test message@
  • & " and @ are just delimiters.
    7 is the function code for GLOBAL_CHAT_SEND
    0 means nothing, no data needs to be sent here
    and data 2 contains the message to send (Hello this is a test message)

Obviously I have code to handle things properly if the user sends a message containing a delimiter character.

Anyway my question is, should i bother using start and finish delimiters? Is byte-byte-String a efficient protocol, and comprehensive enough for sending any type of command? What’s the standard way that most programs send protocols?

  1. Multi-threaded servers I did not use NIO, nor did i use java.concurrent. I created the multi-threaded server from scratch… is there anything I should look out for? I think the threads work well. I use wait() and notifyAll() alot in the objects that need it, so the threads dont consume much CPU (they dont constantly poll the object for changes)

What is the standard way of modelling a multithreaded server? Is my way OK?

  1. The client and server framework can be distributed to anyone, and they could use it to develop their own networked application. To use it, for example a server, they instantiate my main server class, and implement 2 interfaces. The first is ReceiveListener interface, which is where all the received packets from the server go

The 2nd is ServerMessageListener, which listens for server messages, any error messages or whatever is useful for the application.

I’m worried that these 2 points are just two small. My point is, all received packets from the server are redirected down into one single abstract method receivePacket(). Information about the connection is passed down with the packet also, so the application can reply. Do you think this one point of packet flow here is not enough?

  1. Finally Broadcasting

In the server framework, to broadcast, the server simply iterates all connections and sends the packet to them. I’m worried that with a high number of connections, the last one will take significantly longer to receive the packet than the first one. Is this standard practice?

I had the idea of storing the packet to be broadcasted in an object which all the connection threads observe, however, how can I determine when all clients have sent the message and the next broadcasted message can be added onto the queue?

Thanks for reading this long post.

I hope you can help a poor student :slight_smile:

using numbers in variables is useally an indication that something is going wrong, and here I’d say this is one of those cases. Cause I read your explanation and I still can quite put my finger on what the methode is suppose todo. is it a key and value? if so perhaps those are better names.

as far as delimiters go do you need differend ones? what if the string contains characters that are delimiters?

as far as other implications about the network, you’d have to wait for Jeff or others cause I can only add things from hearsay, cause I haven’t done real time tests.

Odd comments…

Strings as commands are okay for games with relatively low packet per second rates. Yould never want to do it for something like a first person shooter though. It takes more work to create, is a l;arger packet to send, and mreo work to interpret then a binary packet protcol.

Nope. strings are inefficient. Binary packets are efficient. See above. Strings are a bit easier to debug though.

Not really the issue. Seperate thread per user is okay for small numerbs of conencting clients. Get up to any large number though and the context switching and memory needs will kill you. Thats why NIO was invented.

Small number of clients, its fine. If you have any intention of supporting large numbers of siumultaneous users, it will bite you in the ass.

No offense, but what you describe is so simple and so limited in terms of scalability Im not sure what the general value is.

shrug totally depends on the app.

First off, the infrstructure you describe will never be able to support enough users to make that an issue.

Secondly if your server infrastructure appraoches even tenths of milliseconds doing what little you describe then something is evry very wrong. The inetrnet has average latenceis of 200+ms so its not likely to be significant.

All in all, I thin kyou have much bigger and more basic scaling worries in your architecture.

actually jeff that also depence on the application, fps-games ppl go about calling it unplayable, well I wouldn’t go as far but the advantage is there. So depending on the app it can come into play, so it worth considering wenn design. However in this situation it’s dismissed quite quickly because iliterating is not very costy.

becasue I can se the replies comming: Jeff IS right, he’s just taking a short-cut. Also to be clear the argumentation is right, I just have some resavations towards the specific 200ms.

ML, I’d respond but I don’t quite understand what you are saying. Sorry.

As for the 200ms+ I shoudl mention that is in the US. Based on some measurements our European members have done, some european countries have better response rates, at least in a local area. OTOH some don’t. (AIR our Brittish friends found pretty good measurements in their area of England (more in the 50-100 ms range), our German friends found about the same latencies as the US.)

Thanks jeff for your comments, and of course, I took no offence, as I am still learning after all.

What I described was indeed one new thread per connection, and you mentioned it wouldn’t scale very well.
What are the alternatives?

What were the solutions before NIO came into play?

Binary packets is another thing you mentioned, I’ll take that into account.

Anything else?

Your comments were very appreciated, thanks

Select based non blocking IO.

in other words, NIO.

Serious server developers wrote JNI code to talk to C sockets.