java rmi multiple clients same application - java

I am trying to do an RMI mastermind application in java, where each client needs a separate game from the server, but somehow the combinations for each new client that runs are appended to one game, so it is as if each new client joins the main game.
Here is my server code:
public class MastermindServer
{
public static void main(String[] args) throws RemoteException, MalformedURLException
{
try
{
java.rmi.registry.LocateRegistry.createRegistry(1111);
System.out.println("RMI registry ready...");
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Exception starting RMI registry");
}
Naming.rebind("//localhost:1111/MastermindServer", new MastermindImplementation());
}
}
and my client code:
public class MastermindClient
{
private static MastermindMenuGUI menuFrame;
public static void main(String[] args)
{
System.out.println("before try catch");
try {
Registry clientRegistry = LocateRegistry.getRegistry("127.0.0.1",1111);
System.out.println("Client registry " + clientRegistry);
MastermindInterface game = (MastermindInterface) clientRegistry.lookup("theGame") ;
System.out.println("Client ready");
System.out.println(game.createCombination());
}
catch (Exception e) {
e.printStackTrace();
System.out.println("Exception in client");
}
}
}
How do I make a new separate game for each client?
Thanks in advance!

The object in the Registry should be a factory object. The client should look it up and then call a factory method which returns a new game, which should be another remote object.

Related

My client wont connect to its server

I have made Client.java and Server.java. Here they are below.
Client
public class Client
{
ClientConnection cc;
public static void main(String[] args)
{
new Client();
}
public Client()
{
try
{
Socket s = new Socket("localhost",4444);
cc = new ClientConnection(s,this);
cc.start();
listenForInput();
} catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}
public void listenForInput(){
Scanner console = new Scanner(System.in);
while(true){
while(!console.hasNextLine()){
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
String input = console.nextLine();
cc.sendStringToServer(input);
}
}
}
Server
public class Server
{
ServerSocket ss;
ArrayList<ServerConnection> connections = new ArrayList<ServerConnection>();
boolean shouldRun = true;
ServerWindow serverWindow;
public static void main(String[] args)
{
new Server();
}
public Server(){
try
{
serverWindow= new ServerWindow();
serverWindow.setVisible(true);
ss = new ServerSocket(4444);
serverWindow.serverLog("Server starting");
while(shouldRun){
Socket s = ss.accept();
ServerConnection sc = new ServerConnection(s,this);
sc.start();
connections.add(sc);
serverWindow.serverLog("A client connected from " + sc.getIP());
}
} catch (IOException e)
{
e.printStackTrace();
}
}
public ServerWindow getServerWindow(){
return serverWindow;
}
}
When i run Client.java and Server.java they connect fine and carry out their tasks as expected. But when I am in a new class and i create a client object and a server object, the client doesnt work properly.
public class tester
{
public static void main(String[] args)
{
Server server = new Server();
Client client = new Client();
client.cc.sendStringToServer("From tester");
}
}
The server works fine, it creates the window as expected but the client object doesnt work. My server object will not recognize a connection like it does when it normally works and my client's message will not go through. What am I missing? Does it have to do with using localhost as the ip?
Your problem is that you block the main thread by calling
listenForInput();
in your Client. Create a new Thread that calls the input listener and you will be fine.
new Thread(new Runnable() {
public void run() {
listenForInput();
}
}).start();
Edit: The same problem is in the Server class. There is an infinite loop, that blocks the Server constructor from finishing. Also add this:
new Thread(new Runnable() {
public void run() {
while(shouldRun) {
Socket s = ss.accept();
// do other stuff
}
}
}).start();
Note: You do not need to sleep the thread when waiting for input. Just write some empty brackets or a semicolon.
while (!console.hasNextLine()) ;

Java: How can I create an application that will only start if an instance of it doesn't exist and call the instance if it does exist?

I am trying to create a program with Java that can only have one instance of it running at a time.
I am using Sockets and ServerSockets to try to achieve this.
How the program is supposed to work is:
The main method will check if any parameters have been passed, it will try to write the first parameter to the server, if it fails that means, that means that this is the only running instance, so it will open the ServerSocket and then start the frame. If it doesn't fail then the application is already running so it should send the string and the other instance should be able to read it and process it.
Here's the main method:
public static void main(String[] args) {
String fileName = null;
if (args.length >= 1) {
fileName = args[0];
}
if (Singleton.sendSignal(fileName)) {
Frame.getFrame().open(fileName);
Singleton.checkInput();
}
}
And here's the server class:
public class Singleton {
private static final int portNumber = 4243;
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static Socket echoSocket;
public static boolean sendSignal() {
try {
echoSocket = new Socket(InetAddress.getLocalHost().getHostName(), portNumber);
PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
out.write("Open\n");
out.close();
close();
return false;
} catch (Exception e) {
close();
return true;
}
}
public static void checkInput() {
try {
renewReader();
} catch (Exception e) {
close();
}
}
public static void renewReader() throws Exception {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine = in.readLine();
if (inputLine.equals("Open")) {
Widget.getInstance().setVisible(true);
}
close();
renewReader();
}
public static void close() {
try {
serverSocket.close();
} catch (Exception e) {
}
try {
clientSocket.close();
} catch (Exception e) {
}
try {
echoSocket.close();
} catch (Exception e) {
}
}
}
Although half of this code works (only one instance runs at a time), only the first set of data are being passed and then the program stops reading. How can I make the socket listen until the program is closed?
I your checkInput() method, you are accepting for client connection once here. Try something like this:
public static void checkInput()
{
//do something here
serverSocket = new ServerSocket(portNumber);
//wait for request from client.
Socket clientSocket = serverSocket.accept();
//
// do your processing here
// call checkInput method again.
checkInput();
}
As soon as another instance it started, server will accept the request, do the processing and then again starts waiting for more requests (for this we called cehckInput again).
Also in your main() add this:
public static void main(String[] args)
{
String fileName = null;
if (args.length >= 1) {
fileName = args[0];
}
if (Singleton.sendSignal(fileName))
{
Frame.getFrame().open(fileName);
// start the server in a thread so that main method can continue on
new Thread()
{
public void run()
{
Singleton.checkInput();
}
}.start();
}
// do your other tasks.
}
On upon termination of program, your sockets will auto close. Also if you want to explicitly close the sockets, you can add a shutdown hook to close it.
A simple hook looks like this.
Runtime.getRuntime().addShutdownHook(your thread that will close sockets);

Java - Iterate through IP Address List and call thread with IP Address as argument

I'm relatively new to Java and I'm writing an application to interrogate an Apache HTTP server's access_log file; with this, I want to submit the IP Addresses individually (probably via the Apache HTTPClient library) to another Java instance on another server (as the Web server does not have FTP enabled) to pull some log files. At the moment I've managed to bumble my way through modifying a 'tail -f' equivalent class to suit the programs needs and then manipulate that data to get the IP Addresses that I need to do something with - I even managed to make the 'tail' class threaded so it could address multiple periods of time!
With that said, I want to use a for loop to iterate through each entry in my computerRebootList String Array and with each address create a thread to perform some more work but all I can think of is this;
for (String tmpIpAddress : computerRebootList ) {
ComputerIpHandler handler = new ComputerIpHandler();
}
and then create another class named ComputerIpHandler like so;
public class KioskIpHandler implements Runnable {
static final Logger logger = LogManager.getLogger( ComputerIpHandler.class );
#Override public void run() {
//do some code
}
public static void main(String computerIp) {
Thread mainThread = new Thread(new ComputerIpHandler());
mainThread.start();
try {
logger.info("log some stuff");
mainThread.join();
logger.info("yay it's done");
}
catch (InterruptedException errInterrupted) {
logger.error(errInterrupted.getMessage());
logger.error(errInterrupted.getStackTrace());
}
}
}
I read somewhere about ensuring that I need to manage resource limitations so I would have to create a maximum number of threads - arguably I could send something like 10 IPs to this class and then have the rest of the addresses 'queue' until the one has returned... I'm just not confident or fluent enough to be able to conceptualise these ideas.
EDIT: I omitted that I am restricted to Java 1.6 as this is the maximum compatible version of the JRE that we can use on this server - not sure if that hinders this effort somewhat...
Can anyone point me in the right direction?
Check ScheduledThreadPoolExecutor and ScheduledExecutorService classes in package java.util.concurrent in java API. Those and some other classes in that package would manage all resources for you. They are available in java since version 1.5
I recommend using Java's built in FTP connection platform to make a thread for continually receiving data on a specified port, until it receives a termination key.
Basically, one class will create a ServerSocket (open socket on server) and upon connection with another socket (the client socket) it would create a new thread for receiving information.
public class Server {
public ServerSocket ss;
public Socket clientSocket;
public Thread receiveingThread;
public BufferedReader inFromClient = null;
public boolean running = false;
public Server(int port) {
try {
ss = new ServerSocket(port);
startReceiving();
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void startReceiving() {
receiveingThread = new Thread("Recieve") {
public void run() {
String dataFromClient = new String("");
while (running) {
try {
inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
dataFromClient = inFromClient.readLine();
} catch (Exception e) {
e.printStackTrace();
}
if (dataFromClient.equals("TERMINATOR_KEY") {
stopRecieving();
}
else if(!dataFromClient.equals("")) {
//add item to array
}
}
}
};
receiveingThread.start();
}
public synchronized void stopReceiving() {
try {
running = false;
receivingThread.join();
ss.close();
clientSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
}
public static void main(String[] args) {
new Server(yourPortHere);
}
}
then the client class would look something like:
public class Client {
public Socket socket;
public Thread send;
public Client(string serverPublicIP, int port) {
try {
socket = new Socket(serverPublicIP, port);
send("some IP address");
} catch (Exception e) {
e.printStackTrace();
}
}
public void send(String toSend) {
send = new Thread("Send") {
public void run() {
PrintWriter outToServer;
try {
outToServer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
outToServer.print(toSend);
outToServer.flush();
} catch (Exception e) {
e.printStackTrace();
}
finally {
outToServer.close();
}
}
};
send.start();
}
public static void main(String[] args) {
new Client("127.0.0.1", yourPortHere);
}
}
This is the link for the start of socket tutorials on the oracle site.
This is the Oracle Documentation for java.net.ServerSocket
This is the Oracle Documentation for java.net.Socket

Is it possible to synchronize two threads over shared Remote Object?

public class RMIClient {
public static void main(String[] args) {
String serverURL = "rmi://" + args[0] + "/GameServer";
String viewURL = "rmi://" + args[0] + "/ViewServer";
try {
GameInterface gameIntf = (GameInterface)Naming.lookup(serverURL);
PlayerView view = (PlayerView)Naming.lookup(viewURL);
while(!gameIntf.getGameOver()){
synchronized(GameInterface.sharedObject){
GameInterface.sharedObject.notify();
System.out.println(view.getMessage());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
if(br.readLine().contains("y"))
gameIntf.setNextMove(true);
GameInterface.sharedObject.wait();
}
}
} catch (MalformedURLException | RemoteException | NotBoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public interface GameInterface extends Remote{
public static final Object sharedObject = new Object();
public void setNextMove(boolean val) throws RemoteException;
public boolean getGameOver() throws RemoteException;
}
Currently when I start rmiregistry, server and start two RMI clients, both clients wait forever after getting 1st input i. e. one client is not notifying other. I am starting RMI clients on same JVM.
No. The stub object at the client is not the same Java object as the remote server in the server host, and synchronizing on it or notifying it doesn't magically propagate across the network to the server or to other clients.
The answers in the link you cited don't support your theory either. You need to read the answers by #MarcH and me, and ignore the others, which are wrong in various ways.

How can I re-spawn a thrift server in java after an exception?

I'm new to java and have written a small, but quite important, thrift service in java.
I've noticed that occasionally it'll stop serving without any error messages; it seems that the java process just dies, randomly, without a stack-trace or exception.
What would be the best way to ensure this process stays alive even after an error? Here's the main function, if it will help:
public static void main(String [] args) {
try {
MyAppServiceHandler handler = new MyAppServiceHandler();
MyApp.Processor processor = new MyApp.Processor(handler);
TServerTransport serverTransport = new TServerSocket(8080);
TServer server = null;
server = new TSimpleServer(processor, serverTransport);
System.out.println("Starting thrift server...");
server.serve();
}
catch (TTransportException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
I've changed to a better solution.
My main function in java looks like this:
public static void main(String [] args) {
try {
MyAppServiceHandler handler = new MyAppServiceHandler();
MyApp.Processor processor = new MyApp.Processor(handler);
TServerTransport serverTransport = new TServerSocket(8080);
TServer server = null;
server = new TSimpleServer(processor, serverTransport);
System.out.println("Starting thrift server...");
server.serve();
}
catch (TTransportException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
This leaves the sever to die, which goes against what I wanted from the original solution. However, the java process/server is now initiated from Supervisor which keeps an eye on the process and respawns it if it dies, whereas the original solution (to use a while loop) would keep the server alive but printing stack traces if there was a problem in connecting to the port, and those error messages would be missed.
if the call to serve is blocking you can do:
public static void main(String [] args) {
while(true){
try {
MyAppServiceHandler handler = new MyAppServiceHandler();
MyApp.Processor processor = new MyApp.Processor(handler);
TServerTransport serverTransport = new TServerSocket(8080);
TServer server = null;
server = new TSimpleServer(processor, serverTransport);
System.out.println("Starting thrift server...");
server.serve();
}
catch (TTransportException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
//do cleanup
}
}

Categories

Resources