[RESOLVIDO] Socket multi thread com conexão persistente (Cliente Flash)

10 respostas
S

Fala galera,

Sou novo aqui e novo no mundo java.

Sou programador AS3, RoR e Python e agora estou me aventurando no mundo Java para realizar um projeto pessoal.

A muito tempo atrás fiz um socket em Python com conexão persistente e agora queria fazer em java.

Segui vários tutoriais, inclusive a maioria dos tópicos aqui do fórum, por isso venho perguntar a vocês.
O último que segui foi esse:
http://www.javareference.com/jrexamples/viewexample.jsp?id=47

Meu cliente é um Flash AS3 e meu socket Server é em JAVA.

O cliente conecta, segura a conexão, manda a mensagem e fico esperando a mensagem no Java, mas ela não aparece.
Quando eu desconecto o flash a mensagem aparece.

Se eu envio várias mensagens do Flash para o Java, nada acontece até eu fechar o flash, quando eu fecho o flash todas as mensagens aparecem.

O que pode ser?

Lembro que quando fiz Flash + Python, eu tinha que mandar um byte zero no fim da string incluindo \0 no final da string.
Mas no Java não tá rolando.

Segue o código:

Classe do Server

public class Server extends Thread {
    static ServerSocket myServer;
    ArrayList clients = new ArrayList<ClientWorker>();
    
    Server(){
        
    }

    public void run() {
        try{
             myServer = new ServerSocket(4321);
        }catch(IOException e){
             System.out.println(e);
        }

        System.out.println(clients.size());
        
        while(true){
            ClientWorker w;
            try{
                //server.accept returns a client connection
                w = new ClientWorker(myServer.accept(), this);
                w.start();

                clients.add(w);

                 System.out.println(clients.size());
            } catch (IOException e) {
                System.out.println("Accept failed: 4444");
                System.exit(-1);
            }
        }
    }

     public void killClient(ClientWorker _client){
        clients.remove(_client);
        _client = null;
        System.out.println(clients.size());
    }
}

Classe da Thread

public class ClientWorker extends Thread  {
    private Socket client;
    private Server server;
    private BufferedReader in = null;
    private PrintWriter out = null;

    ClientWorker(Socket client, Server server) {
        this.client = client;
        this.server = server;
    }
    
    public void run() {
        try{
            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            out = new PrintWriter(client.getOutputStream(), true);

            String line = in.readLine();

            boolean onready = true;

            while (onready) {
                if(line != null){
                    System.out.println("fala:" + line);
                    line = in.readLine();
                }else{
                    in.close();
                    out.close();
                    client.close();

                    server.killClient(this);

                    System.out.println("mata");

                    onready = false;
                    
                    try {
                        this.finalize();
                    } catch (Throwable ex) {
                        Logger.getLogger(ClientWorker.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }                
            }
        } catch (IOException e) {
            System.out.println("in or out failed");
            System.exit(-1);
        }
}

10 Respostas

L

Você está lendo com “readLine”. Está enviando fim de linha (0xD 0xA) no final do seu pacote?

S

Fala leo,

Mesmo enviando esses caracteres no final do pacote não tá rolando.

O que poderia ser, é o pacote que não finaliza?

será q teria outra forma de fazer isso?

L

Olha, seu código funciona rodando e conectando usando o Putty. A cada enter, ele mostra um "fala". Então, está certo. Talvez você pode tentar ler com byte[] ao invés de readLine para ver se alguma coisa chega...

Nunca fiz conexão socket direto com AS3 (nem sabia que o Flash deixava!), então não sei se o problema pode ser nele...

Desculpe não poder ajudar mais.

Edit: O que eu posso fazer é dar uma refatorada nas suas classes para ficar melhor performante... para ficar super-performante, você vai precisar de I/O Assíncrono, usando Java NIO e/ou as bibliotecas Apache Mina ou JBoss Netty...

package snippet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientWorker implements Runnable {
	private Socket client;
	private BufferedReader in = null;
	private PrintWriter out = null;

	public ClientWorker(Socket client) {
		this.client = client;
	}

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(client
					.getInputStream()));
			out = new PrintWriter(client.getOutputStream(), true);

			String line = null; //para poder entrar no loop uma vez...
			boolean onready = true;

			while (onready) {
				System.out.println("Esperando...");
				line = in.readLine();
				if (line != null) {
					System.out.println("falou:" + line);
				} else {
					client.close();
					System.out.println("não falou...");
					onready = false;
				}
			}
		} catch (IOException e) {
			System.out.println("in or out failed");
			e.printStackTrace();
		}
	}
}
package snippet;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

public class Server implements Runnable {
	private final int porta;
	private ServerSocket myServer;
	
	private ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newCachedThreadPool();

	public Server(int port) {
		this.porta = port;
	}

	public void run() {
		try {
			myServer = new ServerSocket(this.porta);
		} catch (IOException e) {
			e.printStackTrace();
		}

		while (true) {
			try {
				//se quiser fazer algo quando terminar ou esperar terminar, guardar o futuro
				Future<?> futuro = executorService.submit(new ClientWorker(myServer.accept()));
			} catch (IOException e) {
				System.out.println("Accept failed: " + this.porta);
				e.printStackTrace();
				break;
			}
		}
		executorService.shutdown();
	}

	public static void main(String[] args) {
		new Server(4321).run();
	}
}
S

Cara, valeu por ter testado…

Deve ser problema do AS3 mesmo, quando fiz com paython penei um pouco até descobrir que tinha q mandar um 0 no final da string.

O que isso que vai fazer altera e melhora no socket?

Desculpe, é q mexo com java a, vamos ver, mais ou menos 3 dias, hahahaha

[]'s

L

O que eu “melhorei” foi o uso de Threads, basicamente. Ao invés de você ficar criando threads, elas são gerenciadas pelo ThreadPoolExecutor. O que você faz é criar instâncias de “Runnable” e passa para o Executor executar. Se ele está cheio, por exemplo, a tarefa fica pendente.

Para melhorar com I/O Assíncrono, você pode ler a documentação do JBoss Netty, que é muito boa!

S

Cara, valeu, vou ver pq o flash aqui tá fazendo isso.

Te adicionei no gtalk qualquer coisa.

[]'s

S

Cara, resolvi…

Os caracteres certo para enviar não é o (0xD 0xA) mas sim os (0x0R 0x0N) ou pra melhorar no flash é só colocar \r\n no final da string enviada.

Finalmente.

Valeu ai…

L

Sim! \r == 0xD e \n == 0xA… Tradução do ASCII!

Resumindo, você tem de mandar final de linha :slight_smile:

S

eita quando eu criava pra mandar 0xD 0xA ele mandava um caracter diferente de \n, \r, hehehe
acho q o flash não traduz certo o ascii aqui rola com 0x0R 0x0N.

H

Mas no caso, poderia disponibilizar outro exemplo, com mais de um servidor, assim, se tenho 2 clinete em um servidro, fica tranquilo, mas na hora que o servidor cair, todos caem, gostaria de saber, se tem como deixar um outro servidor pronto, quando o primeiro cair, o outro já está disponibilizado. Tem como?

Criado 26 de maio de 2011
Ultima resposta 18 de jun. de 2012
Respostas 10
Participantes 3