Bem, já fiz chat usando Socket e agora foi a vez do RMI.
No RMI percebi a facilidade pra chamar métodos remotos, porém vi a dificuldade para fazer um chat multi client.
Ví vários exemplos na internet e vi vários aqui no GUJ, mas nenhum foi como eu imaginei, dai fiz a seguinte GAMBIARRA.
Nos exemplos, o cliente se conecta ao Servidor e envia uma mensagem, no máximo, o servidor imprime essa mensagem, já que não se tem caminho de volta sem que o Cliente fique esperando um retorno. Dai o que acontece se o servidor informar algo que o cliente não está esperando? Nada, o cliente nem sabe que tem que pegar alguma coisa no servidor.
Então pensei, o servidor recebe comandos sem esperar, então o cliente pode ser um servidor também e receber comandos do servidor sem esperar.
Dai fiz o seguinte algoritmo.
Client.java
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import javax.swing.JOptionPane;
@SuppressWarnings("serial")
public class Client extends UnicastRemoteObject implements CRClient {
public Client() throws RemoteException {super();}
public static void main(String[] args) {
CRServer conn;
try {
conn = (CRServer) Naming.lookup("//127.0.0.1/Server1");
try {
String login = JOptionPane.showInputDialog(null, "Poe seu nick ai");
Naming.rebind(login, new Client());
Player player = new Player();
player.setLogin(login);
conn.connect(player);
conn.sendMessage(player, JOptionPane.showInputDialog(null, "Digite uma mensagem"));
conn.disconnect(player);
} catch (Exception e) {
System.out.println("Erro: " + e.getMessage());
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("Client exception: " + e.getMessage());
e.printStackTrace();
}
}
@Override
public void receiveMessage(String msg) throws RemoteException {
System.out.println(msg);
}
}
CRClient.java
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface CRClient extends Remote {
void receiveMessage(String string) throws RemoteException;
}
CRServer.java
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface CRServer extends Remote {
void connect(Player player) throws RemoteException;
void sendMessage(Player player, String msg) throws RemoteException;
void disconnect(Player player) throws RemoteException;
}
Player.java
import java.io.Serializable;
@SuppressWarnings("serial")
public class Player implements Serializable {
private String nome;
private String login;
private CRClient lookup;
public void setNome(String nome) {
this.nome = nome;
}
public String getNome() {
return nome;
}
public void setLogin(String login) {
this.login = login;
}
public String getLogin() {
return login;
}
public void setConn(CRClient lookup) {
this.lookup = lookup;
}
public CRClient getConn() {
return lookup;
}
}
Server.java
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
@SuppressWarnings("serial")
public class Server extends UnicastRemoteObject implements CRServer {
private ArrayList<Player> players = new ArrayList<Player>();
public Server() throws RemoteException {super();}
public static void main(String args[]) {
try {
Naming.rebind("Server1", new Server());
System.out.println("Servidor Iniciado");
} catch (Exception e) {
System.out.println("Erro: " + e.getMessage());
e.printStackTrace();
}
}
@Override
public void sendMessage(Player player, String msg) throws RemoteException {
for(Player playerX : players) {
playerX.getConn().receiveMessage(player.getLogin() + " diz: " + msg);
}
}
@Override
public void connect(Player player) throws RemoteException {
players.add(player);
try {
player.setConn((CRClient) Naming.lookup("//127.0.0.1/" + player.getLogin()));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
System.out.println("Player conectou: " + player.getLogin());
}
@Override
public void disconnect(Player player) throws RemoteException {
players.remove(player);
System.out.println("Player desconectou: " + player.getLogin());
}
}
Se analisarem, vão ver que o Client.java se conecta a Server.java e pede um login ao usuario, após inserir e dar ok, o Client.java abre um servidor e diz pro Server.java que ele agora é um servidor e pode também receber pedidos do servidor.
Foi a única maneira que vi de trocar mensagem como no socket.
Alguem costuma fazer diferente? Ou fiz certo? Ou fiz gambiarra das brabas? hehehe
[Comandos para utilizar]
javac *.java
rmic Server
rmic Client
start rmiregistry
start java Server
start java Client