Java Game Server thread-safe recieving web-socket messages - java

I'm upgrading my python websocket game server to Java, (using Jetty for websockets), and recently started to learn about thread safety.
My challenge is, the game logic (gameRoom instance) runs on the main thread, but the server will be receiving player messages (eg. a message to join a game room), and notifying the game logic FROM ANOTHER THREAD. I originally (in python-when all was on the main thread) just processed the message right away, (eg. add a player on recieving a message). This can lead to problems with multiple threads, as the gameRoom thread might be adding a player at the same time, to the players array. (The players list ends up being shared during adding a player= not thread safe!)
What's the SIMPLEST way to handle recieving messages from a servlet running on it's own threads, and process these messages WITHOUT messing up the game running on the main thread(a different thread)? In my head, i'd imagine some kind of one-way buffer (eg. http://web.mit.edu/6.005/www/fa14/classes/20-queues-locks/message-passing/) to queue new messages to be processed ONLY by the gameRoom itself, during part of the logic. Or is there a way to avoid mulitple threads at all!? *Please give your thoughts, I'd love to hear from someone with more than my begginner level of thread knowledge. I greatly appreciate all tips/ advice :) *
I took the time to make a SIMPLE EXAMPLE showing what's going on (please ignore synax errors, i made it super short for your convinience :) ):
class ServerClass {
static GameRoomClass gameRoom;
static void main() {
//psuedocode start Jetty Server, this server runs in another thread, will call onServerMessage()
jettyServer.start();
jettyServer.onMessageCallback=(onServerMessage); //set message callback (pseudocode)
//create game room, run on main thread
gameRoom = GameRoomClass();
gameRoom.runGameRoom();
}
//when the server gets a message from a player,
//this will be called by the server from another thread, will affect the GameRoom
static void onServerMessage(Message theMessage) {
gameRoom.gotServerMessage();
}
}
//this runs game logic
class GameRoomClass {
ArrayList<E> players = new ArrayList<>();
public void runGameRoom() {
while (true) {
//move players, run logic...
//sometimes, may call addNewPlayer AS WELL
if(...){
addNewPlayer();
}
}
}
public gotServerMessage(){
//this will only be called by the 'Server' thread, but will enter 'addNewPlayer' method
//meaning it will access shared value players?
addNewPlayer()
}
public addNewPlayer(){
//this will be called by the server thread, on getting a message
//can ALSO be called by gameRoom itself
players.add(new PlayerObj());
}
}
class PlayerObj {
//a player in the game
}

The simplest and efficient way is to use one of thread-safe collection classes from java.util.concurrent package.
For the given case ConcurrentLinkedQueue seems to be a good start.

Related

How can I do unit tests on a java socket game that uses a game loop?

The problem
I have finished coding a game in java called Apples To Apples and now I am trying to make unit tests. I have a main class that acts as the server and it supports multiplayer by using socket programming. The constructor of the server consists of setting up the game, adding players and then running the game in a while loop. I have created methods that are called in the while loop for each phase of the game.
I have now created a test class to make unit tests of each method (phases of the game) and this is where my problem arises. I don't know how to access the methods from the server class in the best way. I first tried to make an instance of the server class but this results in the test just running forever waiting for the game to finish. Then I tried to access the methods without instantiating the server class but this results in having to change the methods and some variables to static and I have read that you should avoid making variables static.
So my question is, is there another approach I am missing here or is there anything I can do different?
Simplified version of my problem
public class Apples2ApplesServer{
private String card = "Wildcard!";
public static void main(String[] args){
new Apples2ApplesServer(Integer.parseInt(args[0]));
}
Apples2ApplesServer(int numOfOnlinePlayers){
setupGame();
addPlayers(numOfOnlinePlayers);
// Game loop
while (true){
System.out.print(phaseOne());
}
}
public static String phaseOne(){
return card;
}
}
class Apples2ApplesServerTest {
// My first approach, does not work
Apples2ApplesServer server = new Apples2ApplesServer(1);
#Test
#DisplayName("Test phase one")
void phaseOneTest(){
// My second approach
// Works but phaseOne and card needs to be static
String firstCard = Apples2ApplesServer.phaseOne();
assertEquals("Wildcard!", firstCard);
}
}
If you want to take a look at the entire code you can find it on my github.
Also, this is my first time asking for help here so i'd love feedback on how I presented my problem :)
I believe your problem testing the game loop is very similar to testing other server or daemon code.
Not a real solution, but you might want to check out how other projects like Apache Tomcat go testing their overall server. That too, once started up would keep running until a shutdown command is received.

Why printing all running threads in Java unblocks an application?

I created a GUI Application in JavaFX which communicates with a serial device (I use a jssc connector). When I want to get data I send a communicate, then wait 1s until the wait function terminates. Communicate is also being sent, among other things, when I click one of the buttons (for starting a device, for identification, etc.). During development process I noticed a bug - communication hangs (but only when receiving messages, I still can send one-way communicates for ie. starting a device) when I click too many buttons too fast or I click buttons which send more than one communicate.
Communication is mainly handled by my own class SerialPortDevice. I create an object of a class' type and then invoke particular methods. Here's the method which waits for a message:
private String waitForMessage() throws SerialPortException {
long operationStartTime = System.currentTimeMillis();
long connectionTimeout = SerialPortCommunicationParameters.CONNECTION_TIMEOUT_IN_MILLIS;
String resultMessage = "";
do {
if (readEventOccurred) {
System.out.println();
resultMessage = receiveMessage();
System.out.println("After receiving a message");
messageReceived = true;
}
} while (((System.currentTimeMillis() - operationStartTime) < connectionTimeout) && (!messageReceived));
if (!readEventOccurred) {
resultMessage = NO_RESPONSE;
}
System.out.println("Time elapsed: " + (System.currentTimeMillis() - operationStartTime + "ms"));
return resultMessage;
}
One can notice that message is being received only when a flag readEventOccured is true. It's handled by my implementation of the SerialPortEventListener:
class SerialPortDeviceReader implements SerialPortEventListener {
private SerialPortDevice device;
SerialPortDeviceReader(SerialPortDevice device) {
this.device = device;
}
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR()) {
System.out.println("Serial Event Occured!");
device.setReadEventOccurred(true);
}
}
}
readEventOccured is a boolean field in the SerialPortDevice class which contains waitForMessage function. Also, waitForMessage is invoked by another function, singleConversation:
String singleConversation(String testMessage) {
String resultMessage = NO_RESPONSE;
try {
openConnection();
sendMessage(testMessage);
resultMessage = waitForMessage();
closeConnection();
} catch (SerialPortException e) {
e.printStackTrace();
return resultMessage;
}
System.out.println();
readEventOccurred = false;
messageReceived = false;
return resultMessage;
}
... Which is the only function setting readEventOccured to false. And it is a "top level" function in a SerialPortDevice class which handles sending and receiving a communicates to and from a device.
So communication looks like this:
Button click -> Button handler invocation -> device.singleCommunication(buttons_specific_communicate) -> some methods run and then it comes to the waitForMessage -> method waits 1s for the event -> event occurs (everytime - I get the "Serial Event Occured" communicate) -> readEventOccured is being set to true -> if there is some time left (there is always some time left, everything lasts a miliseconds), message is being received in the waitForMessage method.
There is no problem if I click buttons with a short (in a human sense, 2-3s for example) delay or I don't click these which do send more than one communicate inside their handlers. In different situations weird things happen. I still get the message "Serial Event Occured" (so I suppose readEventOccured is also being set to true) but waitForMessage function does not execute
if(readEventOccured)
statement's code. Also, I have to run an application again to be able to communicate with a device (I mean receiving data, sending works perfectly).
What solved my problem was adding "volatile" modifier to the readEventOccured flag (makes sense by the way, things go fast sometimes). But it didn't please me. I wanted to make a code to run correctly without "volatile". My coworker came up with an idea something goes wrong with threads that are being created when I click buttons and invoke communication - maybe something blocks other thing somewhere? First thing I did was to print all the currently runnig threads and... Man, it solved a problem. App was not hanging anymore. Really, I performed "hanging" scenarios 10-20 times with and without
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
System.out.println(threadSet);
at the beginning of the waitForMessage method and result were unambigous - it somehow removed my problem.
I'm almost certainly sure getting and printing threads is not a solution itself. It's something that is being done by the way but I can't find out what is this. Any useful information? Maybe better understanding Threads in Java would help me? Or it is something else?
Cheers
What you're doing is the textbook example of what happens when there are no visibility guarantees. If we distil your code into its essential bits, we get something like this:
boolean flag = false;
void consume() {
while (true) {
if (flag) {
//we received flag, hooray
}
}
}
void produce() {
flag = true;
}
Now, if produce() and consume() run in different threads, there is absolutely no guarantee that consume() will EVER see flag set to true. volatile creates a memory barrier, meaning that all reads/writes of those variable will be fully ordered.
What you also have in the code though, is lots of System.out.println() lines. These complicate the picture, as they themselves are synchronized, and thus create happens-before relationships between different parts of the code. Unfortunately they don't create the correct sequence, but poke in a few more and you can accidentally get it right. The key word here is "accidentally", you shouldn't rely on this behaviour at all.
So marking readEventOccurred as volatile sort of fixes the problem but going a bit further we can see that your waitForMessage() spin-waits, which is rarely a good idea. I would take a look at the CountDownLatch class for example, designed for similar scenarios. (An even better candidate is its close friend, CyclicBarrier.)
What solved my problem was adding "volatile" modifier to the readEventOccured flag (makes sense by the way, things go fast sometimes). But it didn't please me. I wanted to make a code to run correctly without "volatile".
The fact that adding volatile fixes the problem indicates you've run into the lack of guarantees by the Java Memory Model when multiple threads are involved. Simply put there is no guarantee of when a change on one thread is visible on other threads except for specific situations.
The probably reason why printing 'fixes' the problem is the fact that it:
Changes the timing of the program, might mean the situation in which it fails no longer exists.
Temporarily suspends the threads to read out their current state, maybe the JVM also uses that as an opportunity to synchronize memory.
Multithreaded communication is hard, so I recommend you take a look at the classes available in java.util.concurrent, which have guarantees that you might be able to use to solve your problem more elegantly.

JavaFX beans/properites and multithreading

I must say that I'm new to Java and JavaFX (less than 2 months), and also my UML skills are not perfect, so I might have used wrong blocks or/and connectors on the diagram :) But I hope you get an idea.
I have an order management app with a following (simplified to essentials) design:
OMS app design
Put very simply, the JavaFX GUI displays in a table view what is happening (i.e. the current state of the orders) between the client (that sends orders) and the broker (on the other end of the network connection). Order Manager is the only entity that has access to modify the model (i.e., the list of orders and their fields), and all methods modifying the model are synchronised (so it's safe to call them from any thread).
The orders are JavaFX beans, with different fields implemented as JavaFX Properties. These properties are bound to table columns in the GUI, so whenever the Order Manager updates a field, the change is propagated to the GUI via the binding mechanism.
Now, because the property binding mechanism is not thread-safe (see the following rule:
An application must attach nodes to a Scene, and modify nodes that are already attached to a Scene, on the JavaFX Application Thread.
), I have to wrap all the code modifying those fields, in Platform.runLater() calls, for example:
public void onOrderCanceled(int id, String reason) {
Order order = orderbook.get(id);
if(order == null) {
throw new IllegalArgumentException("Order "+id+ " not found");
}
Platform.runLater(() -> {
order.setReason(reason);
order.setStated(CANCELED);
subscribers.foreach(sub -> sub.notifyUpdated(order));
});
}
This approach has the following unpleasant implications:
The client notification is delayed by an arbitrary time (till the GUI thread finishes processing its message queue). Reason: I cannot notify the client before the order fields are updated (or it will have incorrect data), and I can only update the fields in the GUI thread.
Because the state of the order is not modified right away but at some future point, there exists for some time an incoherence between the order object and the actual order state.
If the GUI thread gets blocked or becomes very slow (because of bugs or design flaws), the client code is blocked or slowed down (while waiting for the notification that is stuck in the GUI thread's message queue).
Is there a better way of doing that? Ideally, I would like a solution that:
Allows the client code to communicate with the networking layer (via the order manager) as fast as possible, i.e. without waiting for the GUI to catch-up
The GUI is allowed to lag behind a little bit, but must not "skip" field updates, or at least never drop the most recent update (which is the most relevant)
Rely on the FX property binding architecture to update the GUI (which I find very convenient)
I feel that I need to create another "model" for the GUI that will be updated in the FX thread only, while the "real" model will be used by the order manager and the client code, and I need to ensure to maintain the two models in sync (which is creepy).
Was FX designed without multithreading in mind? I had a look on the Task and Service interfaces, but is doesn't look like something appropriate (in my case, GUI doesn't initiates a task - it comes from an external source, the client code or the network).
Thanks in advance!
If I understand this implementation correctly, you are performing the notification to remote clients on the FX Application Thread. You're doing this because you need to send the clients the updated version of the Order object, and since this object is bound to the table, changes to its state can only happen on that thread.
This is somewhat perilous, as those remote notifications may take time, and so you may block the UI thread, causing a lack of responsiveness. Additionally, you are forcing the logic of the application to wait for the (potentially blocked) UI thread. This is the opposite way around to the way you should be doing things: your application logic should flow in a thread of execution in a natural way, and you should arrange for the FX Application Thread to show the latest version of the data in as lightweight a way as possible on each frame rendering.
I think what you need here is a separate, immutable class to represent the updates. You'll send those to your clients, and then on successful notification update the UI, instead of driving the application from the UI. So something like
public abstract class Update {
private final int orderId ;
public Update(int orderId) {
this.orderId = orderId ;
}
public abstract void performUpdate(Order order) ;
public int getOrderId() {
return orderId ;
}
}
and
public class Cancelation extends Update {
private final String reason ;
public Cancelation(int orderId, String reason) {
super(orderId);
this.reason = reason ;
}
public String getReason() {
return reason ;
}
#Override
public void performUpdate(Order order) {
if (order.getId() != getOrderId()) {
throw new IllegalArgumentException("Wrong order");
}
order.setReason(reason);
order.setState(CANCELED);
}
}
Now in your application code you can do something like
public void onOrderCanceled(int id, String reason) {
Order order = orderbook.get(id);
if(order == null) {
throw new IllegalArgumentException("Order "+id+ " not found");
}
Task<Update> updateTask = new Task<Update>() {
#Override
public Update call() throws Exception {
Update update = new Cancelation(id, reason);
subscribers.forEach(sub -> sub.notifyUpdate(update));
return update ;
}
};
updateTask.setOnSucceeded(e -> updateTask.getValue().performUpdate(order));
updateTask.setOnFailed(e -> {
Exception exc = updateTask.getException();
// handle exception
});
subscriberNotification.execute(updateTask);
}
Now you schedule updates in an executor dedicated to that particular functionality, and then update the UI when you know the notification has happened. In other words, the UI responds to the application logic, instead of the other way around. Your clients now receive the details of the update, and presumably they have their own representation of the Order (perhaps instances of the same class), and can update their own representations using the information in the Update. Note this will likely save you network traffic too (probably the biggest bottleneck in your application), because you only communicate the changes, instead of the entire object. Of course, this might entail some major refactoring of your code (sorry about that...).
It's going to be important that the updates are all transmitted in the correct order, so you should use a single thread of execution for managing them. In other words, you need something like
private final Executor subscriberNotification = Executors.newSingleThreadedExecutor();

Exclusive access established by another Thread Java smartcardio

All,
I have appreciated many helpful answers on this site but I have found a need to post my first question (if you notice anything to be improved in my post let me know).
I have a modest sized Java program with GUI that is acting as a "middleman" and controller. On one end of the information flow it sends and receives data via an HTTP server. On the other it is interacting with an API where data is ultimately exchanging with a SmartCard. In the "middle" is the GUI, logging, and some other features.
There is also a feature (initiated via the GUI) to occasionally load an update to the SmartCard. Otherwise exchanges with the SmartCard are initiated over HTTP.
The problem is when switching between these 2 modes (communicating http to smartcard and then switching to loading the update or vice versa).
When I do that I have concluded I run into the problem of
CardException: Exclusive access established by another Thread
as thrown by sun.security.smartcardio
Searching the web shows the code that exception appears to come from is
void checkExclusive() throws CardException {
Thread t = exclusiveThread;
if (t == null) {
return;
}
if (t != Thread.currentThread()) {
throw new CardException("Exclusive access established by another Thread");
}
}
My first thought was I needed to instantiate the SmartCard API each time I need it (and then set it back to null) instead of once for the entire program like I had initially.
This works for the exchanges over http and I figure it is because each request to the handle() method is a new thread.
In the GUI the update is initiated by an ActionEvent which makes an instance of a CardUpdate. Inside that class then gets an instance of the SmartCard API.
I thought maybe I'd have better luck if when actionPerformed triggered I put the actions on a different, temporary, thread. So far, no.
The closest I got was using something like:
SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
as found at on Sun's website
Using that I could do an update and then go back to http exchanges but I couldn't do another update (per the one time use stipulation of SwingWorker)
I then tried making multiple SwingWorker as needed doing something like
private class GUICardUpdate extends SwingWorker<Integer, Void > {
but then I was back to my original problem. I have also tried to just do a simple additional thread off the GUI class in this fashion:
public class GUI extends javax.swing.JFrame implements ActionListener, Runnable
but this is no different.
Maybe I don't understand threads well enough or maybe I am overlooking something simple. Anyone have any ideas?
Thanks!
As far as I got you are using javax.smartcardio package (directly or indirectly) to work with your card. Some thread (created by you or by the framework you are probably using on top of javax.smartcardio) invoked beginExclusive() method on the Card instance to ensure exclusive access to the card.
The exclusive access is necessary as treatment of the data kept on the IC cards is state-depended, so the proper selection of data files and reading of their records requires the actions of application layer not to be interfered with actions of some other application or thread. For this purpose these three Card interface methods beginExclusive(), endExclusive() and checkExclusive() exist.
So you should check your(framework) code if it calls beginExclusive() and then doesn't call endExclusive().

java gui and logic

it s 3 hours i m tring to understand a thing but no success...
the problem is:
i have a class Gui( a client) with a main for a cardgame. the Gui has a main that has in an invokelater a Runnable where the logic ( a separate class managing the gamesession) runs and some methods to manipulate the order of the cards.
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
PokerClientGui gui = new PokerClientGui();
gui.setVisible(true);
PokerClient pokerClient = new PokerClient(gui);
pokerClient.gameSession();
}
});
}
The logic is created in the main of the Gui passing the Gui itself to the logic.
As far as i am proceding in the program there are no problems since all the objects/strings sent from the server to the client logic are received and for example the Hand is passed to the gui and displayed correctly.
The problem comes now: i want to pass from the gui to the logic, the manipulated hand to send it to the sever via method of the logic class.
Since this function is called by the event mouse on the Gui (and not in the main of the Gui) i have no handle to the logic object so i can t use its sending objects method.
I tried changing to static the method of the logic that sends and i made statics also the member involved in sending things on the socket.....
it doesn t send anything ..... it s not a problem of something wrong and i try to catch the exceptions (and nothing comes from them)
where m i wrong? what i am missing ? how should i bind the gui and the logic?
Perhaps you could create an event queue in your Runnable() class, and pass it to both your gui and your client constructors.
The client would add events for the GUI to display, and the GUI would add events for the client to process. It might be easier with two queues, one for each direction, rather than re-using a single channel for both directions.
Then your GUI and your client would add the event queue from this object into the list of things to 'check' when waiting in their event loops. When an event comes from the other object, it wakes the current object to do processing, same as events from the server or the user.
In place of creating the object of PokerClientGui in main class u better create its object directly in the PokerClient object and access its object gameSession() .

Categories