synchronize between multiple clients in a server - java

I have a Server that can receive multiple request at the same time.
In my Server, I have to make some traitement and wait for response. This traitmenet is done by externe library so I don't how much should I wait.
So the Server looks like :
public class MyServer{
#Override
//method from the library
public void workonRequest(){
//---
response=[...]
}
public void listenRequest() {
new Thread(() -> {
while (true) {
try {
socket = server.accept();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
socket.setTcpNoDelay(true); //TODO : Not sure !
new Thread(() -> {
try {
handleRequest(input, output);
} catch (IOException e) {
throw new RuntimeException(e);
}
}).start();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}).start();
}
And the handle request method is :
public void handleRequest(ObjectInputStream input, ObjectOutputStream output) throws IOException {
try {
while (true) {
//forward the request to the library
//work on it [means using the library and waiting]
// return response
}
}
}
The response object is the result that I want return to the client
How to deal with the problem of waiting for the answer?
How can I make sure that there will be no problems when more than 2 clients send requests at the same time.
Thanks in advance

How to deal with the problem of waiting for the answer ?###
Using while(true) can create issues because you are blocking the thread and opening sub thread and multi streams will make it more complex. There is easy way called reactive programming which handles this kind of multi-threaded issues easily, quarkus async solution and spring, if you still want to manage your sockets from java code you can use akka
How can I make sure that there will be no problems when more than 2 clients send requests at the same time.
That can be done by not blocking the main thread and If you manage to use reactive and/or async approach you will not have that problem.
Reference
https://quarkus.io/guides/getting-started-reactive
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html

Related

How to make Vert.x EventBus.send process requests sequentially?

I'm new to vert.x and would like to know if its possible to configure eventbus somehow to make it work consistently?
I mean need to send requests one by one using vert.x
At the moment I got this code which uses eventloop principle and waits until all handlers finished, but I don't need this done that fast, idea is to free server from lots of requests at the same time. Here eb_send() uses default EventBus.send() method. In other words I want to execute all requests with blocking, waiting for answers before requests.
List<Future> queue = new ArrayList<>();
files.forEach(fileObj -> {
Future<JsonObject> trashStatusHandler = Future.future();
queue.add(trashStatusHandler);
eb_send(segment, StorageType.getAddress(StorageType.getStorageType(fileInfo.getString("storageType"))) + ".getTrashStatus", fileInfo, reply -> {
Entity dummy = createDummySegment();
try {
if (reply.succeeded()) {
//succeded
}
} catch (Exception ex) {
log.error(ex);
}
trashStatusHandler.complete();
});
});
The basic idea is to extract this into a function, which you would invoke recursively.
public void sendFile(List<File> files, AtomicInteger c) {
eb_send(segment, StorageType.getAddress(StorageType.getStorageType(fileInfo.getString("storageType"))) + ".getTrashStatus", fileInfo, reply -> {
Entity dummy = createDummySegment();
try {
if (reply.succeeded()) {
//succeded
}
// Recursion
if (c.incrementAndGet() < files.size()) {
sendFile(files, c);
}
} catch (Exception ex) {
log.error(ex);
}
});
}

Java Kryonet servers, client not receiving server response

I am trying to teach myself some networking in Java using the Kryonet library. The following code is almost identical to the code in the kyronet tutorial. https://code.google.com/p/kryonet/#Running_a_server
The client is successfully sending the message "Here is the request!" to the server (the server is printing it out) however the client is not receiving any response from the server even though the server is sending one.
I've tried unsuccessfully to fix it, can anyone see or suggest a possible problem/solution with the code?
(The code follows)
Client
public class Client_test {
Client client = new Client();
public Client_test() {
Kryo kryo = client.getKryo();
kryo.register(SomeRequest.class);
kryo.register(SomeResponse.class);
client.start();
try {
client.connect(50000, "127.0.0.1", 54555, 54777);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
client.addListener(new Listener() {
public void received (Connection connection, Object object) {
if (object instanceof SomeResponse) {
SomeResponse response = (SomeResponse)object;
System.out.println(response.text);
}
}
});
SomeRequest request = new SomeRequest();
request.text = "Here is the request!";
client.sendTCP(request);
}
}
Server
public class ServerGame {
Server server = new Server();
public ServerGame() {
Kryo kryo = server.getKryo();
kryo.register(SomeRequest.class);
kryo.register(SomeResponse.class);
server.start();
try {
server.bind(54555, 54777);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
server.addListener(new Listener() {
public void received (Connection connection, Object object) {
if (object instanceof SomeRequest) {
SomeRequest request = (SomeRequest)object;
System.out.println(request.text);
SomeResponse response = new SomeResponse();
response.text = "Thanks!";
connection.sendTCP(response);
}
}
});
}
}
Response & Request classes
public class SomeRequest {
public String text;
public SomeRequest(){}
}
public class SomeResponse {
public String text;
public SomeResponse(){}
}
After many hours watching youtube videos and sifting through the web I found the answer. Which I will post on here as it seems that quite a few people have had this problem so I would like to spread the word.
Basically the client would shut down immediately, before it could receive and output the message packet. This is because "Starting with r122, client update threads were made into daemon threads, causing the child processes to close as soon as they finish initializing.", the solution is "Maybe you could use this? new Thread(client).start();".
So basically instead of using
client.start();
to start the client thread you must use
new Thread(client).start();
Which I believe stops the thread being made into a daemon thread which therefore stops the problem.
Source: https://groups.google.com/forum/?fromgroups#!topic/kryonet-users/QTHiVmqljgE
Yes, inject a tool like Fiddler in between the two so you can see the traffic going back and forth. It's always easier to debug with greater transparency, more information.

ActiveMQ register listener to StompConnection

I'm using a variation of the example at http://svn.apache.org/repos/asf/activemq/trunk/assembly/src/release/example/src/StompExample.java to receive message from a queue. What I'm trying to do is to keep listening to a queue and perform some action upon reception of a new message. The problem is that I couldn't find a way to register a listener to any of the related objects. I've tried something like:
public static void main(String args[]) throws Exception {
StompConnection connection = null;
try {
connection = new StompConnection();
connection.open("localhost", 61613);
connection.connect("admin", "activemq");
connection.subscribe("/queue/worker", Subscribe.AckModeValues.AUTO);
while (true) {
StompFrame message = connection.receive();
System.out.println(message.getBody());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
but this doesn't work as a time out occurs after a few seconds (java.net.SocketTimeoutException: Read timed out). Is there anything I can do to indefinitely listen to this queue?
ActiveMQ's StompConnection class is a relatively primitive STOMP client. Its not capable of async callbacks on Message or for indefinite waits. You can pass a timeout to receive but depending on whether you are using STOMP v1.1 it could still timeout early if a heart-beat isn't received in time. You can of course always catch the timeout exception and try again.
For STOMP via Java you're better off using StompJMS or the like which behaves like a real JMS client and allows for async Message receipt.
#Tim Bish: I tried StompJMS, but couldn't find any example that I could use (maybe you can provide a link). I 'fixed' the problem by setting the timeout to 0 which seems to be blocking.
even i was facing the same issue.. you can fix this by adding time out to your receive() method.
Declare a long type variable.
long waitTimeOut = 5000; //this is 5 seconds
now modify your receive function like below.
StompFrame message = connection.receive(waitTimeOut);
This will definitely work.

How to facilitate communication between the server thread and the multiple client threads in Java

I'm trying to create a client server game using java sockets. I have a thread server which controls the logic of the game. I also have client threads that communicate with the server. I use multiple client handler threads to facilitate server-to-client communication. I use multiple threads to communicate with other client threads using sockets.
Now, I have a problem on how to facilitate communication between the server thread and the multiple client threads. For example, should the server select the next player to play, how should it signal the client handler thread, and in turn communicate with the client thread through sockets?
I have done this before in the following way. I have a Server socket
public Server(int port, int numPlayers) {
game = new PRGameController(numPlayers);
try {
MessageOutput.info("Opening port on " + port);
ServerSocket clientConnectorSocket = new ServerSocket(port);
MessageOutput.info("Listening for connections");
while (!game.isFull()) {
// block until we get a connection from a client
final Socket client = clientConnectorSocket.accept();
MessageOutput.info("Client connected from " + client.getInetAddress());
Runnable runnable = new Runnable() {
public synchronized void run() {
PRGamePlayer player = new PRGamePlayer(client, game);
}
};
new Thread(runnable).start();
}
} catch (IOException io) {
MessageOutput.error("Server Connection Manager Failed...Shutting Down...", io);
// if the connection manager fails we want to closedown the server
System.exit(0);
}
}
Then on the client side, I have something like this..
public void connect(String ip) {
try {
comms = new Socket(ip, 12345);
comms.setTcpNoDelay(true);
// get the streams from the socket and wrap them round a ZIP Stream
// then wrap them around a reader and writer, as we are writing strings
this.input = new CompressedInputStream(comms.getInputStream());
this.output = new CompressedOutputStream(comms.getOutputStream());
this.connected = true;
startServerResponseThread();
} catch (IOException e) {
ui.displayMessage("Unable to connect to server, please check and try again");
this.connected = false;
}
if (connected) {
String name = ui.getUserInput("Please choose a player name");
sendXML(XMLUtil.getXML(new NameSetAction(name, Server.VERSION)));
}
}
/**
* This method sets up the server response thread. The thread, sits patiently
* waiting for input from the server, in a seperate thread, so not to hold
* up any client side activities. When data is recieved from the server
* it is processed, to perform the appropriate action.
*/
public void startServerResponseThread() {
// create the runnable that will be used by the serverListenerThread,
// to listen for requests from the server
Runnable runnable = new Runnable() {
public void run () {
try {
// loop forever, or until the server closes the connection
while (true) {
processRequest(input.readCompressedString());
}
} catch (SocketException sx) {
MessageOutput.error("Socket closed, user has shutdown the connection, or network has failed");
} catch (IOException ex) {
MessageOutput.error(ex.getMessage(), ex);
} catch (Exception ex) {
MessageOutput.error(ex.getMessage(), ex);
} finally {
(PRClone.this).connected = false;
// only shutdown the server if the listener thread has not already been
// destroyed, otherwise the server will have already been shutdown
if (serverListenerThread != null) {
// shutdown the thread and inform the application the communications has closed
MessageOutput.debug("Shutting down server listener Thread");
}
}
}
};
// create the thread
serverListenerThread = new Thread(runnable);
// start the thread
serverListenerThread.start();
}
The client is able to send requests to the server via the outputstream, and read server data from the input stream.
The server can accept requests from the client, and process it in the GameController, and can also send notifications from the server using outputstream, again in the GameController.
EDIT: Also, I should note that all my communication is done via XML, and the controller on the client or the server decodes the XML and performs the relevant request.
Hope this helps. It certainly does the job for me, and allows my multi-player games to work well.
I suspect that your client threads are hanging on a blocking read operation. To "release" these threads and make them send data instead, you'd have to interrupt them through thread.interrupt(). (Which would cause the blocking read to throw an InterruptedException.)
However, I've written a few network games myself, and I would really recommend you to look into the java.nio packages and especially the Selector class. Using this class you could easily make the whole server single-threaded. This would save you a lot of headaches when it comes to synchronizing all those client threads.
I think using an existing communication infrastructure like ActiveMQ would be very useful here to deal with the low-level piping stuff and allow you to tackle the game design issues at a higher conceptual level rather than dealing with the low-level intricacies.
That being said. If I understood you then you have a game-client with mutiple threads, one of which deals with comms to the server. On the server there is a comms thread for each client and the game server logic.
I would only use sockets for remote communication and Queues for communication between the server threads. On the queues send immutable objects (or copies) back and forth so you do not need to synchronize access to the data in the messages. As a base for synchronisation you can block on the Socket or a BlockingQueue, then you do not need to manually synch things, however this requires careful protocol design.

Synchronization in threads for Java

I have a home grown web server in my app. This web server spawns a new thread for every request that comes into the socket to be accepted. I want the web server to wait until a specific point is hit in the thread it just created.
I have been through many posts on this site and examples on the web, but cant get the web server to proceed after I tell the thread to wait. A basic code example would be great.
Is the synchronized keyword the correct way to go about this? If so, how can this be achieved? Code examples are below of my app:
Web Server
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.run();
///////////////////////////////
wait here until notifed to proceed
///////////////////////////////
} catch (Exception e) {
e.printStackTrace(logFile);
}
}
Thread code
public void run() {
//code here
//notify web server to continue here
}
Update - Final code is as below. The HttpRequest does just call resumeListener.resume() whenever I send a response header (of course also adding the interface as a separate class and the addResumeListener(ResumeListener r1) method in HttpRequest):
Web Server portion
// server infinite loop
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
request.addResumeListener(new ResumeListener() {
public void resume() {
//get control of the lock and release the server
synchronized(locker) {
locker.notify();
}
}
});
synchronized(locker) {
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.start();
//tell this thread to wait until HttpRequest releases
//the server
locker.wait();
}
} catch (Exception e) {
e.printStackTrace(Session.logFile);
}
}
You can use java.util.concurrent.CountDownLatch with a count of 1 for this. Arrange for an instance of it to be created and shared by the parent and child thread (for example, create it in HttpRequest's constructor, and have it retrievable by a member function). The server then calls await() on it, and the thread hits countDown() when it's ready to release its parent.
You probably need to use a Java Condition. From the docs:
Conditions (also known as condition
queues or condition variables) provide
a means for one thread to suspend
execution (to "wait") until notified
by another thread that some state
condition may now be true.
First of all, I echo the sentiment of others that re-inventing the wheel here will most likely lead to a variety of issues for you. However, if you want to go down this road anyway what you are trying to do is not difficult. Have you experimented with Jetty?
Maybe something like this:
public class MyWebServer {
public void foo() throws IOException {
while (true) {
//block here until a connection request is made
ServerSocket socket = new ServerSocket();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
MyRequest request = new MyRequest(socket);
request.addResumeListener(new ResumeListener() {
public void resume() {
locker.notify();
}
});
synchronized(locker){
//create a new thread for each request
Thread thread = new Thread(request);
//start() the thread - not run()
thread.start();
//this thread will block until the MyRequest run method calls resume
locker.wait();
}
} catch (Exception e) {
}
}
}
}
public interface ResumeListener {
public void resume();
}
public class MyRequest implements Runnable{
private ResumeListener resumeListener;
public MyRequest(ServerSocket socket) {
}
public void run() {
// do something
resumeListener.resume(); //notify server to continue accepting next request
}
public void addResumeListener(ResumeListener rl) {
this.resumeListener = rl;
}
}
Run under a debugger and set a breakpoint?
If unfeasible, then read a line from System.in?

Categories