Estou fazendo um cliente de msn, como tarefa de aprendizado.
Por enquanto, está apenas em modo texto.
Organizei as classes da seguinte maneira:
*Messenger.java -> responsável pelos métodos referentes ao programa, como mudar de status, por exemplo;
*Comunica.java -> responsável pela comunicação com o servidor;
A classe Comunica, implementa Runnable, de forma que tem um método com um loop infinito, e threads consultam este método, para verificar se o servidor enviou alguma mensagem.
A classe Comunica, foi feita de maneira que, apenas uma instância dela é permitida (nao lembro o nome desde Design Pattern).
Meu problema é que, como havia dito, crio threads para consultar a classe comunica, porém, nao posso simplesmente criar uma thread nova, pois a comunicação (feita por sockets) se dá na thread que estabeleceu a conexão e, se eu criar uma nova thread, nao haverá comunicação com ela.
Criei um método, através do qual, eu passo o objeto que está se comunicando com o servidor, e, desta maneira, funcionou corretamente, mas eu gostaria de saber se não há uma maneira melhor de fazer isto.
Aqui estão minhas classes:
package messenger;
public class Messenger {
int cont = 0;
String host;
int porta;
String user;
String pass;
Comunica comunica;
public Messenger(String us, String ps){
comunica = Comunica.getInstance();
user = us;
pass = ps;
}
public void shutdown(String msg){
System.out.println(msg);
System.exit(0);
}
public void conectaMSN(){
String resposta = "";
host = "messenger.hotmail.com";
porta = 1863;
comunica.conectaServidor(host, porta);
comunica.enviaComando("VER " + cont++ + " MSNP9 CVR0\r\n");
resposta = comunica.recebeResposta();
//etc
//este método faz a conexão do usuario no servidor
}
public void sincronizaLista(){
comunica.enviaComando("SYN " + cont++ + " 0\r\n");
String resposta = comunica.recebeResposta();
}
public void mudaStatus(String st){
comunica.enviaComando("CHG " + cont++ + " " + st + "\r\n");
String resposta = comunica.recebeResposta();
}
public static void main(String[] args) {
Messenger ms = new Messenger(usuario,senha);
ms.conectaMSN();
ms.sincronizaLista();
ms.mudaStatus("NLN");
Comunica cmn = Comunica.getInstance();
cmn.recebeObjeto(ms.comunica);
new Thread(cmn).start();
}
}
package messenger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Comunica implements Runnable {
private static Comunica instancia;
Socket socket;
InputStream rStream;
OutputStream wStream;
private Comunica(){
}
public synchronized static Comunica getInstance(){
if(instancia == null)
instancia = new Comunica();
return instancia;
}
public void conectaServidor(String h, int porta){
try {
InetAddress host = InetAddress.getByName(h);
socket = new Socket(host,porta);
rStream = socket.getInputStream();
wStream = socket.getOutputStream();
} catch (IOException e) {
System.out.println("Erro ao conectar com o servidor!");
e.printStackTrace();
}
}
public void recebeObjeto(Comunica cm){
try {
rStream = cm.socket.getInputStream();
wStream = cm.socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void enviaComando(String cmd){
try {
wStream.write(cmd.getBytes());
wStream.flush();
} catch (IOException e) {
System.out.println("Erro ao enviar requisição ao servidor");
}
}
public String recebeResposta(){
String response = "";
try{
do{
response += (char)rStream.read();
}while(rStream.available() > 0);
System.out.print(response + "\n");
} catch (IOException e) {
System.out.println("Erro ao receber resposta do servidor");
e.printStackTrace();
}
return response;
}
public void run(){
//fica esperando mensagens do servidor
while(true){
try {
if(rStream.available()>0)
this.recebeResposta();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Grato
Julio Romano