As part of a learning experiment, I want to make a network application. I'm still learning about multithreading, and I've made a simple multithreaded "game" that involves drawing sprites on the screen, where the player can move them.
For this new project, I want to make something simple, just for the experience and learning. I want to create a server, where multiple clients can connect to it. The server will contain "game objects", which is just an object containing an x and y position, a string name, an ID to identify it, and velocity (dx and dy).
The "server" application will feature things like a worker thread updating the position of the objects (using their velocity), and it will also send the client the "state" of all game objects, so the clients can draw them for the players to see.
The clients will also send the server data whenever the player presses a button on the keyboard and generates a KeyEvent. The server will read this data and process it by updating the player's game object. For example, if the player presses the left arrow key, the client will send the server data indicating that the left key was pressed, the server will find the game object associated with the client (maybe I will store the objects in a Map like ?)
The problem is how to do this. I've never done any networking of this scale before. The most I've made so far is a buggy 2 player tic tac toe game. Since that is turn based, it is very different the application that I am now trying to make. As research, I read the entire Concurrency lesson on Oracle. I also read this tutorial on NIO. I've never used NIO before but I was recommended by multiple people to use it. I learned a lot about multithreading and concurrency from reading the code and figuring out how it works.
Since the SocketChannels communicate using ByteBuffers, one strategy I thought of is to take a List of GameObjects and serialize it to a byte array. Then create a ByteBuffer with the ByteArray and send it to the client. The client will then get all the GameObjects loaded in the server, and be able to draw all of them based on their type and states. One problem with this is that the byte array could get very large. I tested it with 256 GameObjects, and got a byte array of up to 9KB. If I compress the byte array, the size will be around 96 bytes. Still, I don't know if this is too big to be sent to the client 15 times a second.
Another option that I know of is to send the info byte by byte. For example, the first byte sent could identify what type of game object I am sending (example: cat, car, person), the next two bytes could identify the X position, then the next two the Y position, then the last byte used to identify the state of the object. Using this data, the client can just draw a sprite on the position received.
A big problem with all that I've said is that the client won't be able to interact with any of the objects. The client will just be able to send simple commands to the server, and "view" the game objects' sprites at its position. If the server wanted to tell the a game object to do a specific action, it would be hard to draw it since I will just be drawing static sprites to a screen, instead of interacting with the sprites.
I also am not sure whether or not NIO is the best idea. Most people I've talked to recommend it, but I don't quite understand the practical difference between implementing a non blocking NIO server and a multithreaded regular java.net.* server. My guess is that the non blocking server has better performance than a multithreaded one, and I would run into much less problems with just 1 thread rather than multiple threads per connection.
And finally, I've gotten mixed advice whether or not to use TCP or UDP. I've never used UDP before either. Some strongly suggest TCP, while others strongly suggest UDP.
As you can see, I am pretty unorganized and not sure on what to do. I feel like I have read a lot about networking and concurrency, and I already know enough about Swing to make graphical games. I just don't know how to put it all together.
Perhaps consider using Netty. I have found it extremely useful for rapid application development and fast enough for most server and client applications. You can get faster with a raw implementation of the reactor design pattern with Java NIO, but it will take a lot more work and code that is hard to debug.
Related
I have a general question about programming the client/server communication on a network game.
I use TCP as protocol, and the communication ... works, but I'm not sure, if it is a efficient way.
In general , actions that happen on the client-side will go throught all this steps:
Some action (eg. a Fireball is cast)
[*]For this action i defined a string (eg. #F#270#130#, which means the 'F' says it's a fireball and 270 is (for example) the degree of the angle, 130 - the speed of the fireball that is shoot.)
String goes into outputpuffer of Client & waitingqueue
String is sent
String is received by server
[*] Server needs a lineinterpreter that can detect the meaning of the string (here : what means F? It is a fireball!) & adds a unique identity, based on, from which client the command was received.
[*]The Server needs to calculate logic, based on the action happened (fireball does damage to someone, does it hit someone (immediately) or does it just fly first?)
Server sends an (updated) string of the action(s) that occur to all clients. (eg. maybe the fireball is slowed down in speed for some reason - here will be an updated string (#F#12345#270#90# - 12345 is the unique player identity)
clients receive string
[*] clients resolve string to a command + handle it (fire an animationsequence...)
client that originaly sent the command compares received string with string in waitingqueue - when equal, do nothing (to smoothe out some action, otherwise through connection problems /delay, some action would occur twice or jump from location to location, based on ping
Is it really necessary to go through all these steps? At all steps marked with [*] i need to define new lineinterpreters/action for each command, so i'm coding each action twice, client & server-side.
I read something about sending serializable objects, but in genereal the idea seems to be the same to me, i send an object, that has to be interpreted+handled and i send an object back...
Any hints? To solve the whole communication more elegant, with less coding ? Or a bit more sorted - all these #F# #M# #H# tags for different actions are making it more and more complicated :)
(In fact i actually have the following handlers/actions:
-move
-look/rotate
-hpchange
-firearrow
-spawn/disconnect
...)
Hope you understand what I mean - I know, I could just continue coding like that, and it would work somehow, but it just seems too complicated as it could be.
Thanks!
You could do it in a more OO way if you:
Define an object called Action or something like that, which has all of the above parameters - type of action, direction of action (or
target), damage dealt, etc..
Create those Action objects as your game normally executes
Use ObjectOutputStream chained to your TPC Socket to output the whole Action object to the server/ pass it back to the client.
On the server, interpret what happens by examining the recieved object from ObjectInputStream.
I think this way would be cleaner and more flexible in case you add more logic, than just analyzing strings, but not as fast (since objects going into ObjectOutputStream need to be serialized).
You need to look at several factors before you decide if your game requires any changes.
Firstly, is TCP the best communication channel? Have you compared it to UDP. Would it be better to implement the networking using UDP? Would it matter if a few packets went missing? What happens if the network is slow?
Secondly, look at how often you are polling/pushing to the server. Can this be reduced? Does the game have to be in real-time. Do all parts of a game have to be in realtime. Perhaps certain things can be non-realtime. A fireball will continue in a straight path so you dont have to keep updating the server about its position, you can just tell it about its direction and speed. What other aspects of the game can be non real-time. The only thing that needs sending is, players locations and actions. Most other things like collision detection can be offloaded to the client.
Thirdly, does every keypress need to be sent to the server? If the user is against the wall and wants to move further, the client knows that they cannot and thus will not send those keypresses to the server. If the user has moved to a new valid location, then update the server. Can certain things be buffered and sent to the server in one go, instead of sending several queries to the server. i.e. if I move forward, jump and throw a fireball, thats 3 keypresses on the client side, can they be buffered and sent at the next 500th millisecond?
If you are worried about the networking overhead, you should be working at the bit level. Instead of sending a long string "#F#270#130#" - which is 11 bytes long, would it make sense to send 3 consecutive bytes (24 bits).
7 bits represent the action (127 different actions).
9 bits will represent the angle (1-512), but you only need it up to 0-360 degrees.
8 bits represent the force.
This or any other byte format is shorter and easier to use over the network, and produces tighter code. Also binary comparison is faster, so writing your action parser on the server is now made easier. I.e. instead of a large switch case looking for #F#, you just look at the first 7 bits and compare it to an int.
Can you reduce other networking overheads, instead of force being decided by the client, can the server decide this. i.e. a standard force, or 2 levels of force (much better as this can be represented by 1 bit). Which stops the client and malicious users sending rubbish data across to the server (like force of 999), now the force can either be a 0 or a 1, i.e. speed of 10 or 20, nothing silly.
I'm quite new to Java and have just started Networking so I apologize in advance for any stupid questions. I have a basic game in which a player (or bot) can move around a map until it finds items and exits, but using networking I'd like to be able for the player and the bot to play on the same map simultaneously over a server.
I have 5 classes:
GameRules - Controls the game logic/rules
Map - Contains the map.
Player - Represents a player.
Bot - Plays the game as a bot.
PlayGame - Controls the interaction with the game through CLI.
I'm pretty sure GameRules and Map would be on the server side, and PlayGame would be on the client side, however I'm not sure where Bot and Player class stand? And also, do I merge GameRule and Map into one class, or put a socket in each class?
Thanks a lot.
Most models in a client-server game should reside both on client and server.
The client needs the models to visualize the data they are holding;
The server needs them to modify them according to business logic - the intermediate results are then sent to the clients to have their models updated. The server must do this because that is the reason for its existence: keeping the game's state consistent by being the only node that can alter the game state.
You can always try to keep all models at the clients but imagine what coding horror you'll get yourself into when you want to make a game with N clients. They all have to have a consistent state. It is far more safe to have one node (server) make decisions and then the other nodes must follow instructions.
Please note that in more advanced implementations, like realtime games, the client also implements some prediction behavior to hide the client-server delay, and thus temporarily alters the game state, but the server commands always overrule the client's decisions. You also can code the client in such a way that he is always able to keep playing even when he didn't receive a confirmation yet for the previous "moves" from the server - you have to implement rollback/correction functionality when some moves are denied by the server.
Depending on the complexity of the business logic and synchronization timing needed, it's entirely possible to keep most everything at the client level, and just use the server as a broker for updates. Imagine a 2-player online chess game. The rules are so standard and the timing is simply back-and-forth, so a "server" of this game need only pass each move back and forth from one player to the other. Would be like replacing the mail in your grandfather's chess match with a socket. Each (client) side knows exactly how to process the move and what new moves are valid.
I've have recently been exploring my own idea to make a little multiplayer game that a couple of my friends could play just for the fun of it. I know all the basics, a little more to java, i would consider myself an intermediate at java.
Recently I've been learning on how to load sprites, double buffering, key listeners, mouse listeners, etc for making a little side scroller 2d gun game. And I have a good understand of these categories, but now I've come to the part where I need to learn about sockets and such to be able to get this game online.
I've seen a little tutorial on where a server and client were made, and when the client was opened would send a message (string) to the server, for example "Orange" and the server could understand that, and print it out. I can understand the code by looking at it (if asked to reconstruct that from my own knowledge (slash memory) would be unable to, because I don't know sockets).
Now to my main question, how can I start to go about doing something like this, when doing this, how to a registrated the movement,for example, from one client to the server which would then appear on all clients connected and in the game, as well with bullets, collision events, enemies, etc. I cant seem to find any good help out there that really shows you how to do this, by creating a socket, doing all the basic connection stuff (which i dont know) and then updating the game state if i can call it that.
So in all, how can I basically take a game with has a ground, two players (represented by sprites) some enemies (AI) and bullets able to kill the enemies, and the ability for the enemies to fire back and kill the players (Users) and make a server and client out of it? Oh and one more thing, I'd like to have the ability for the player to choose a name as well, and the name lets say would float above the players character in the game... And if is even possible to have a little built in chat function, but i might be getting to advanced on that one.
If someone can just at least point me in the right direction, or explain the basics around all this, then that would be great! Thanks!
-Dan
I apologize if I through a lot out there, I just want to explain what im looking to be able to do
What you will need is a multithreaded server, that listenes for incomming data from the players, and then update accordingly. The client also needs to be threaded and listen for incomming data from the server so it can update other players movement etc. So start by reading up on sockets and threads. You want the server to create one thread for each client that is connected.
Then make a first try by sending messages to a server, which echos back the same messages to the client. This will require that you use threads and sockets and is a good way to start.
You will be using the same tequniqe for your game later (clients send their movement to the server, and the server echos the movement to all the other clients so they can update the changes locally) OR, the clients send movements to the server, the server updates the movements locally. This will require that the clients get x and y cordinates of all the objects stored on the server. This might be better in case of lag (never programmed a game so not sure which approach will be best).
So, you will have infinite loops on both the server and the clients that each iteration gets/sends x and y axis of each object and use that to repaint/handle hits and so on. Which logic lies in which loop will depend on the design you choose.
I have designed a real time Physics simulation with NIO,
which is about moving balls simultaneously (real time) on multiple clients
Currently, i m sending the coordinates of one ball with string parsing,
but now i want to move multiple balls and want to have some generic mechanism other than sending string, so i create 4 balls on server.
How it can be realize that, coordinates of each ball correspond to same ball on client (which i created on client too), and each ball can be move according to its received coordinates from the sever.
This should be realize by sending the reference of each ball but i don't have idea how to realized that with java byte buffer and with NIO overall.
I have the problem with implementation, if somebody help me with code example , it would be great, anyway which can be generic for sending simulation data like object coordinates other than strings can be acceptable(if somebody did similar work) but it should implement the usecase as i described.
Thanks,
Jibbylala
P.S : May i know the reason of Downvoting question?
first things first:
you need an object identity to represent the moving/whatever stuff. The object has properties just like any other Object in java,in your case the ball has coordinates. Possibly the ball has shape (besides being a perfect sphere w/ a constant R), you'd like to send the description or type of the object 1st and then the change of some of its properties.
For object identity you can use a single long or even an UUID but represented by 2 longs (16ytes)
You can even use standard java serialization but I'd advise against unless you are versed into the matter (but you'd not have asked the question then).
While making a binary protocol is not hard in order to replace your own string-based representation, it's also not an easy task for a first timer.
NIO, itself, features ByteBuffer, however that should not impose any effects on the external/stream model you represent your data. If you are able to represent "the balls" into some meaningful way into a byte[], you can achieve the same with ByteArray.
Use RMI with KryoNet, then you just use remote method calls and the calls are efficient enough that you no longer need to worry about them. There's RMI examples on the site for you to get started with. If you need realtime client interaction with the simulated balls it becomes a bit more complicated, and you might need to use UDP, but otherwise you can just send the positions. You should attempt to consolidate the information into maybe a method in your world object.
I am trying to implement my own remote desktop solution in java. Using sockets and TCP/UDP.
I know I could use VNC or anything else, but its an assignmentwork from school that I want to do.
So for moving the mouse and clicking I could use the Robot class. I have two questions about this:
What about sending the video? I know the Robot class can capture the screen too, so should I just send images in a sequence and display in order at the other side of the connection? Is this the best way to implement remote desktop?
Also should I use TCP or UDP?
I think UDP would be harder to implement since I will have to figure out which image comes after the other.
What you are trying to do will work, but incredibly slow. The images must be compressed before you send them over the net. Before compressing, the number of colors should be reduced. Also, only the portions of the image which have changed since the last update should be sent.
When transferring mouse coordinates an update should only occur if the new mouse position is more than x pixels away from the last position away or a number of y seconds is over. Otherwise you spend so much traffic for the mouse position that there is no room for the images.
UDP will be the best solution here, since it is fastest for video streaming (which is what you are effectively doing).
About 2:
UDP would be much harder, since it's a datagram-based protocol there are limits on how much data you can send at a time; it's not very likely that you are going to be able to fit entire images into single datagrams. So, you're going to have to work with differential/partial updates, which becomes complicated pretty quickly.
TCP, however, is stream-based and only delivers data in-order. If a packet in the middle disappears and needs to be re-sent, all following packets need to wait, even if they've been received by the target machine. This creates lag, which is often very undesirable in interactive applications.
So UDP is probably your best choice, but you can't design it around the assumption that you can send whole images at a time, you need to come up with a way to send just parts of images.
Basically a video is a sequence of images ( frames ) displayed by second. You should send as much as your bandwidth allows you.
On the other hand, there is no point to send the raw image, you should compresss it as much as you can, and definitely consider lose a lot of resolution in the process.
You can take a look at this SO question about image compression if you compress it enough you may have a vivid video.
It will be better if you use Google Protocol buffer or Apache thrift. You will send binary data which will be smaller - by this, your software will work faster.