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.
Related
I'm trying to write multiplayer game for Android with java back-end using sockets, but I don't know how to do some things.
For example, I have to players. First player pushed "UP" button and his avatar moving up. How can I tell about it to all other players?
I can send message, that user with some ID changed his coordinates to new X and Y, but I will need to do that for every millisecond while he moving. Is that right?
Or I can send message that user with some ID pushed UP button and after that new message that user released UP button. Using time difference between this two events and movement speed I can calculate new coordinates of user, but in this case will be problems with latency (time difference calculation will be not enough accurate)
How I can do that?
You can do it in lot of ways and all will have drawbacks like you already found. I guess there is no "best" way to do that.
A common way for games is to have a "game server". The server recieves input from all clients and decides about the resulting state.
Clients could for example just transmit the keypresses and the server tells them about their location and location of other clients that need to be drawn. Clients do the same math locally and display this state while waiting for confirmation from the server. But that's just a prediction.
When it lags you can observe yourself jumping between positions in a lot of games because actual server calculated position and your prediction got out of sync.
The other advantage of server-side state decisions is that clients can't cheat that easily. It's no foolproof way to prevent every cheat. Aim-bots for example simply simulate a perfectly aiming user by moving the mouse for them and that's basically not detectable. Map hacks / wall hacks (anything where you can see things that you would not see) on the other hand can be prevented by simply not telling the client about currently invisible things. Only the server needs to know the full state.
The server approach can also be used without a dedicated game server. Instead, one of the clients will have the role of the server and decide about the game state. That responsibility can in some games even switch between clients if the original host drops out. A smooth handover if that happens is rather tricky though.
If there is no server and all clients are equally responsible you will have to think about schema which defines which client is responsible for validating which action. For example in a shooter, A shoots in a certain direction, and thinks B is still there but B already moved a bit further and now A thinks "B was hit" and B thinks "shot missed" -> Either the one shooting or the one being hit should decide what happens.
A schema with multiple decision making parties might not work for every game and it is a very complicated task. Not just for games but distributed computing in general
Java and Sockets are just tools here. The actual problem is one where you should take pen and paper and think about a schema that works for your scenario.
Regarding coordinates every milisecond: you could also send messages like "I will be at point X,Y at time Z" and other clients interpolate the path of that player so you don't have to transmit every position.
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.
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.
Is it best to communicate between two scrabble boards on separate computers by creating a cloud with a SQL table, simulating the board. And every time I move is made you contact the server and update the local board?
Sounds good to me. Scrabble doesn't require real-time millisecond precision, so using database transactions to consummate the board moves sounds like a good approach.
In your shoes, I'd try to formalize my states a bit more. If you think of it, a Scrabble game consists of:
A board
The coordinates on that board that give bonuses (x2 letter, x3 word, etal.)
The set of available letters, and the amounts of each letter available, and the point-score for each letter
A profile for each player
The set of letters in each Player's possession
The words each player has played, and where they are on the board
The player's current score
A dictionary of allowable words (for challenges)
A lot of this can be stored in an SQL database - for instance, a player's name and score. But an SQL DB might be too heavy for things like the board coordinates and how various bonuses map to various coordinates. If you think of it, these are static, read-only attributes that will never change from game to game. It might make sense to represent them as a serialized 2-D array, or something similar. Same goes for the dictionary of allowable words. In your shoes I'd be tempted to read the dictionary from a text file on server start-up, store the strings into a non-mutable array, and hand-code an ultra-fast binary search rather than suffer through the overhead of database calls to an indexed table.
Likewise the grab-bag of letters: do you really need a database for this? Maybe you do. Maybe you decide that, since the grab-bag represents mutable state that's going to be shared between all connected clients, you want to take advantage of your DB's locking mechanisms. Or maybe speed becomes an issue, so you find that an array or a list serves you better, and you're comfortable managing the thread-state yourself.
The point is that you won't know what to choose until you spell out what you're doing with some degree of precision. Then you can begin to consider the trade-offs.
Storing the board state in a central DB is fine - and good design. It's unclear how you are planning on having each client handle communications, you have a couple of options:
client 1 make a move, send details to server (persisting state in DB)
server pings client 2 notifying them that it is their move (use a remoting technology to ping)
Same as step 1 but for client 2.
Or
client 1 make a move, send details to server (persisting state in DB)
client 2 polls server until it notices that it is it's turn.
Same as step 1 but for client 2.
So, you have to consider whether you want 2-way client-server communication (client calls server, server calls client) or whether you want 1-way client server communication (clients calls server, including polling to determine when state has changed).
There are some good answers here but I would say it really all depends on what you have available. If you can assume that there is a central server available, then using it to keep track of game state would be a good idea, as it would not lock down the clients to any particular machine - they can go from one to another during the game if they wish. There would also be some extra security here, as you can detect clients that are trying to make illegal moves. And I'm sure there are other benefits too. The most obvious downside would be that this requires a server (i.e. a third piece of hardware, along with a web address and hosting, etc.).
If you can't make that assumption, there's really nothing wrong with making one client the 'server'. It just comes with different pros and cons.
As for using an SQL table, rtperson made some very good observations.