This is a school project, please do not provide any code, I am only looking for hints to guide me in the right direction.
Write and test a game server that clients subscribe to. Once subscribed, the client receives
a list of games (the same game, just different 'instances' of it) currently in play. The client may then elect to join a game or start a new
one. A game must have at least two players before actually starting. The system must support multiple clients all playing one game, or multiple clients playing multiple games.
The objective of this project is to gain experience in Java, TCP, and threading.
My current design and implementation has 2 files: server.java and client.java
The server file has 3 classes: Server, Lobby and Game
The client file has 1 class: Client.
The implementation of the "game" is trivial, I am fine with that.
Currently, the server class establishes the TCP connection with the client class.
Each time a client is instantiated, the socket is accepted in the server class, and the program continues.
Continuing on, the server class creates the lobby class.
The lobby class is where I am having trouble with. By default, I am creating 1 "game" object, and passing in the clientSocket:
game g = new game(clientSocket, playerID);
g.start();
The game class extends thread, which I think is the correct way of doing it. Each "game" will be a separate thread, so to speak, so players A and B can share 1 thread, and players C and D can start a new game with another thread.
I am new to threads, but this is the best implementation I could think of. I ruled out having multiple threads for lobby's, since that doesn't really make sense, and multiple threads for clients is pointless too, so I think multi-threading the games class is ideal.
Right now, when I create 2 instances of the client, they are both joining the same 'thread' (they are both in the same game and can talk to each other).
How am I supposed to do it so that, a new player can type "new" or whatever in the lobby and create a new "game", where it's a new thread.
I'm sure I mis-understood certain parts about threading or whatnot, but I appreciate any help.
I wouldn't map games to threads. Instead, map clients to threads. Each client will have their own thread that does work initiated by the receipt of commands from that client. When you need to create a new game, just create a new object in a shared collection of games. Track, in the client instance, which game, if any, it's associated with.
If you find you really do need a thread to manage a game, then you can create one. When a client sends a command to a particular game, just put that command on a queue of commands that's read by the thread managing that game. The game thread only needs to know which game it's managing. It can terminate itself when that game is finished.
Firstly, I would suggest you read on multiplayer game development and networking in Java (UDP/TCP). I am no game-developer but simply happenned to take a Java networking course in college and had a similar project (a networked game).
Secondly, dealing with multiple threads is proportional to complexity. You want to minimize complexity. I would suggest to abandon an "I have to find a place to use threads" mentality. (Don't force a square peg in a round hole ;))
Continuing, following through the requirements:
Write and test a game server that clients subscribe to.
IIRC, this is fairly straightforward (and you're probably past this part).
Once subscribed, the client receives a list of games (the same game, just different 'instances' of it) currently in play
This should be fairly straightforward as well since a TCP connection between the server and client have been established already.
However, there are a couple of things to understand at this point. The most important, perhaps, is that there will be a single central server that will hold information on all connected clients and existing games. This consequently means that it has to be the one to deal with the state of the system (e.g. tracking currently existing gamerooms), client requests (to create/join gamerooms), as well as updating clients with relevant info on the system's state (e.g. created/closed gamerooms).
Another consideration at this point is the scope of client's functionality in the system. A typical implementation would probably be a fat-server, thin-client architecture. Basically, this means that a client does no real processing of data (from user input) and instead relies on the server. Most of the time, then, the client is only waiting for input from user or a response from the server. On the otherhand, the server deals with the processing of data from clients, updating the system state (including individual game states), and notifying concerned client of relevant changes in the system/game state.
The client may then elect to join a game or start a new one
What actually happens here is a client sending data "I elect to join a game" or "I elect to create a game" to the server. The server acts on this and notifies concerned clients (I say concerned and not all since some clients could possibly be playing and do not need to know whether new games have spawned).
A game must have at least two players before actually starting.
-
The system must support multiple clients all playing one game, or multiple clients playing multiple games.
Again depending on the client-server architecture, either the server will be doing all the processing (fat-server, thin-client) or the clients (thin-server, fat-client) do the processing while the server mainly serves as a relay point to other clients. I have no definite (or even confident) suggestion on this, however, as I am simply overwhelmed by the sheer number of possible implementations and their consequences. Thus, I can't really encourage enough to read more on networking and game development. Individually, those 2 topics are incredibly vast, much more when combined.
Lastly, with regards to the use of threads. IIRC, dispatching separate threads for opened sockets are useful in preventing the application from getting blocked waiting for input. I don't really agree with your idea of "hosting" a game in a thread but since you're in school I can only admire your trying things out.
This may help you further: Lesson: All About Sockets. And you might perhaps also be interested in UDP.
Related
I become desperate, I develop a simple multi-user chat in Java based on the client-server principle. I already wrote a basic multi-threaded server application and it works great. My problem is the client on the basis of the Swing GUI Toolkit. A basic UI with a runtime loop for receiving messages in the background. My problem is that I want to separate the socket logic from the UI, this means that in the best case I've two different classes one for the socket runtime loop and another to manage the UI. Because of the problem, that the runtime loop must notify/add messages to the UI, they depend on each other.
MessengerView is my main class which contains the swing ui and all depended components. At the moment this class contains also the socket logic, but I want to extract them to an external class.
ClientRuntime the class which should hold the socket logic...
My question is, how could I separate them and how could I connect them? For example I tried swing-like events with registering of methods like this:
addListener(MessageArrivedListener listener);
emitMessageArrivedEvent(String message);
The problem is, that it is very confusing if the count of events raises! As already said my second options is to hold socket logic and ui design in one class, but I think it's a bad idea because it makes it very hard to write unit tests for it or to find bugs...
In my time with C++ I used sometimes friend-classes for this issue, because this makes it possible to access class members of other classes! But this solution is often also very confusing and I found no such option for Java.
So are there any other possibilities to hold the connection between the swing widgets and the socket logic, without storing them in the same class (file)?
how could I separate them and how could I connect them?
Connect them with BlockingQueue - this the first choice when choosing ways to connect threads.
ClientRuntime class must start 2 threads: one takes requests from the blocking queue and sends them to the server, and the second constantly reads the messages from the server through the socket and sends them to the UI thread. The UI thread has already input blocking queue for messages: it is accessed by SwingUtilities.invokeLater(Runnable);. The ClientRuntime class does not access UI queue directly: it calls a method from MessengerView and passes what it received from the socket, a binary array or json string, and that UI method converts it to some Runnable which actually updates the UI.
they depend on each other
Well, they don't really. The "socket" layer only cares about been started, running, posting some messages and stopping.
How all that actually get done/handled it doesn't care about, it just "starts" when told, processes input/output messages, posts notifications and "stops" when asked to.
This is basically an observer pattern, or if you prefer, a producer/consumer pattern.
So the socket layer needs to define a "protocol" of behaviour or contract that it's willing to work with. Part of that contract will be "how" it generates notifications about new messages, either via an observer or perhaps through a blocking/readonly queue - that's up to you to decide.
As for the UI, it's a little more complicated, as Swing is single threaded, so you should not block the UI with long running or blocking operations. This is where something like a SwingWorker would come in handy.
It basically acts a broker between the UI and the mechanism made available by the socket layer to receive messages. Messages come from the socket layer into the SwingWorker, the SwingWorker then publishes them onto the UI's event thread which can then be safely updated onto the UI
Maybe start with Concurrency in Swing and Worker Threads and SwingWorker
My question is, how could I separate them and how could I connect them? For example I tried swing-like events with registering of methods like this:
The problem is, that it is very confusing if the count of events raises!
I don't think so (IMHO). What you want to do is focus on the "class" of events. For example, from the above, you have "life cycle" events and you have "message" events. I'd start by breaking those down into two separate interfaces, as those interested in "message" events probably aren't that interested in "life cycle" events, this way you can compartmentalise the observers.
The important concept you want to try and get your head around is the proper use of `interfaces to define "contracts", this becomes the "public" view of the implementations, allowing you devise different implementations for different purposes as you ideas change and grow. This decouples the code and allows you to change one portion without adversely affecting other parts of the API
I am looking at using netty to implement a server for an AI bot competition. The chat example is a good start since the protocol I have designed is similar to a line based chat server, except for one major difference. The bots are asked to make a turn and have a maximum time limit to respond. If a bot fails to respond in time, the server will take a default action for that bot.
In particular I'm implementing The Resistance game. A leader will pick a team and then all the bots have to submit a yes or no vote. I want to wait until either all bots have voted or a timeout (eg. 2 seconds) occurs, in which case I will assign an action for the bots that have yet to respond.
How can I implement this using Netty?
My solution to this problem is to have a Game object running on a thread that uses CountDownLatch to wait upto the timelimit and collects all the votes from the Netty handlers. Any missing votes are given a default vote.
If I want to avoid having a thread for each game, I have built a Fiber library which provides cooperative lightweight threads. Then each Game object can be a fiber load balanced between a thread per CPU core.
I'm writing a game in which players write AI agents that compete against one another, on the JVM. Right now the architecture looks like this:
A core server module that handles the physics simulations, and takes messages from the players as input to alter the world. The core also determines what the world looks like from the perspective of each of the players, based on various rules (think fog of war).
Player modules receive updated versions of the world from the core, process them, and stream messages to the core as inputs based on that processing.
The idea is that the core is compiled along with two player modules, and then the simulation is run producing an output stream that can be played back to generate visualization of the match.
My question is, if each of the players runs on a single Java thread, is it possible to ensure that the two player threads get equal amounts of resources (CPU time, primarily, I think)? Because I don't control the nature of the processing that each AI is doing, it's possible that one of the players might be extremely inefficient but written in such a way that its thread consumes so many resources the other player's AI is resource starved and can't compete fairly.
I get the feeling that this isn't possible without a hard realtime OS, which the JVM isn't even close to being, but if there's even a way to get reasonably close I'd love to explore it.
"Player modules receive updated versions of the world from the core, process them, and stream messages to the
core as inputs based on that processing". This means that player module has a loop inside it which receives update message and sends result messages to the core. Then I would use lightweight actor model, each player being an actor, and all actors use the same ExecutorService. Since activated actors go through the same executor task queue, they got roughly the same access to CPU.
Your intuition is right that this isn't really possible in Java. Even if you had a real-time OS, someone could still write a very resource intensive AI thread.
There are a couple of approaches you could take to at least help here. First be sure to give the two player module threads the same priority. If you are running on a machine that has more than 2 processors, and you set each of the player module threads to have the highest priority, then theoretically they should both run whenever they have something to do. But if there's nothing to stop the player modules from spawning new threads themselves, then you can't guarantee a player won't do that.
So short answer is no, you can't make these guarantees in java.
Depending on how your simulation works, maybe you can have a concept of "turns". So the simulation instructs player 1 to make a move, then player 2 makes its move, and back and forth ,so they can each only make one "move" at a time. Not sure if this will work in your situation though.
If you have any knobs to turn regarding how much work the threads have to do (or just set their priority), you can set up another thread that periodically monitors threads using ThreadMXBeans and find their CPU usage using ThreadInfo.getThreadCpuTime. You can then compare each players CPU time and react accordingly.
Not sure if this is timely and accurate enough for you, but over time you could balance the CPU usage.
However, splitting the work in packets and using Executors like suggested before should be the better way and more java-like.
I am developing a text-based game, MUD. I have the base functions of the program ready, and now I would like to allow to connect more than one client at a time. I plan to use threads to accomplish that.
In my game I need to store information such as current position or health points for each player. I could hold it in the database, but as it will change very quick, sometimes every second, the use of database would be inefficient (am I right?).
My question is: can threads behave as "sessions", ie hold some data unique to each user?
If yes, could you direct me to some resources that I could use to help me understand how it works?
If no, what do you suggest? Is database a good option or would you recommend something else?
Cheers,
Eleeist
Yes, they can, but this is a mind-bogglingly stupid way to do things. For one thing, it permanently locks you into a "one thread per client" model. For another thing, it makes it difficult (maybe even impossible) to implement interactions between users, which I'm sure your MUD has.
Instead, have a collection of some kind that stores your users, with data on each user. Save persistent data to the database, but you don't need to update ephemeral data on every change.
One way to handle this is to have a "changed" boolean in each user. When you make a critical change to a user, write them to the database immediately. But if it's a routine, non-critical change, just set the "changed" flag. Then have a thread come along every once in a while and write out changed users to the database (and clear the "changed" flag).
Use appropriate synchronization, of course!
A Thread per connection / user session won't scale. You can only have N number of threads active where N is equal to the number of physical cores / processors your machine has. You are also limited by the amount of memory in your machine for how many threads you can create a time, some operating systems just put arbitrary limits as well.
There is nothing magical about Threads in handling multiple clients. They will just make your code more complicated and less deterministic and thus harder to reason about what is actually happening when you start hunting logic errors.
A Thread per connection / user session would be an anti-pattern!
Threads should be stateless workers that pull things off concurrent queues and process the data.
Look at concurrent maps for caching ( or use some appropriate caching solution ) and process them and then do something else. See java.util.concurrent for all the primitive classes you need to implement something correctly.
Instead of worrying about threads and thread-safety, I'd use an in-memory SQL database like HSQLDB to store session information. Among other benefits, if your MUD turns out to be the next Angry Birds, you could more easily scale the thing up.
Definitely you can use threads as sessions. But it's a bit off the mark.
The main point of threads is the ability of concurrent, asynchronous execution. Most probably, you don't want events received from your MUD clients to happen in an parallel, uncontrolled order.
To ensure consistency of the world I'd use an in-memory database to store the game world. I'd serialize updates to it, or at least some updates to it. Imagine two players in parallel hitting a monster with HP 100. Each deals 100 damage. If you don't serialize the updates, you could end up giving credit for 100 damage to both players. Imagine two players simultaneously taking loot from the monster. Without proper serialization they could end up each with their own copy of the loot.
Threads, on the other hand, are good for asynchronous communication with clients. Use threads for that, unless something else (like a web server) does that for you already.
ThreadLocal is your friend! :)
http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html
ThreadLocal provides storage on the Thread itself. So the exact same call from 2 different threads will return/store different data.
The biggest danger is having a leak between Threads. You would have to be absolutely sure that if a different user used a Thread that someone else used, you would reset/clear the data.
I have a server for a client-server game (ideally the basis for small MMO) and I am trying to determine the best way to organize everything. Here is an overview of what I have:
[server start]
load/create game state
start game loop on new thread
start listening for udp packets on new thread
while not closing
listen for new tcp connection
create new tcp client
start clients tcp listener on new thread
save game state
exit
[game loop]
sleep n milliseconds // Should I sleep here or not?
update game state
send relevant udp packet updates to client
every second
remove timed out clients
[listen for udp]
on receive, send to correct tcp client to process
[listen for tcp] (1 for each client)
manage tcp packets
Is this a fair design for managing the game state, tcp connections, and send/receive udp packets for state updates? Any comments or problems?
I am most interested on the best way to do the game loop. I know I will have issues if I have a large number of clients because I am spawning a new thread for each new client.
That looks like a reasonable start to the design. It wouldn't be bad to go beyond 10 clients (per your comment) in terms of scaling the number of threads. As long as the threads are mostly waiting and not actually processing something you can easily have thousands of them before things start to break down. I recall hitting some limits with a similar design over 5 years ago, and it was around 7000 threads.
Looks like a good design. If I were you I would use an existing nio framework like netty.
Just google java nio frameworks and you'll find several frameworks with examples and documentation.
Update
Thanks, but I prefer to do it all on my own. This is only for a side project of mine, and much of its purpose is
imho you'll learn more by using an existing framework and focus on the game design than doing everything by yourself from start.
Next time you'll know how do design the game and that makes it easier to design the IO framework too.
I'd say that (especially) in Java, threads are more for convenience than for performance (there are only oh-so-many cores, and I guess you'd like to keep some control on which threads have priority).
You haven't said anything about the volume of message exchange and number of clients, but you might want to consider more natural from the perspective of having a single thread handling the network IO, and having it dispatch incoming requests in a tight loop, and mapping the ACTUAL work (i.e. requests that you can't handle in the tight loop) to a thread pool. IIRC, in such a setup the limiting factor will be the maximum number of TCP connections you can wait for input on simultaneously in a single thread.
For increased fun, compare this with a solution in a language with has more light-weight threads, like in Erlang.
Of course, as #WhiteFang34 said, you won't need such a solution until you do some serious simulation/use of your code. Related techniques (and frameworks like Netty where you could find inspiration) might also be found in this question here.
There is a certain cost to thread creation, mostly the per-thread stack.