Erro: Envio e recebimento String(Socket TCP)

17 respostas
M

Boa noite, galera.

To quebrando a cabeçaa e mto pra resolver isso. Ja fiz minha aplicação toda, só falta a parte de socket, o que seria…

Seria uma aplicação cliente-servidor(pode ser 2 ou na msm maquina, tanto faz), onde eu teria que enviar uma String, dae o servidor deveria receber essa String e fazer operações com ela.

Só que ta acontecendo este erro:

java.net.SocketException: Socket closed
	at java.net.SocketOutputStream.socketWrite(Unknown Source)
	at java.net.SocketOutputStream.write(Unknown Source)
	at java.io.DataOutputStream.writeBytes(Unknown Source)
	at Remota.enviar(Remota.java:137)
	at enviaThread.run(enviaThread.java:26)
	at java.lang.Thread.run(Unknown Source)

Linha 26: r.enviar(string);
Linha 137: dataOut.writeBytes(string);

Ou seja, eu tenho um ponteiro “r”, onde aponto para uma classe Remota que possui um metodo enviar(), onde ele recebe a String como parametro e envia para o servidor.

Só que ocorre este erro, na msm coisa na operação de receber, onde fico esperando com o dataInt.readUTF(); uma string para dps trata-la.

Agradeço a atenção de todos.

Abraço!

17 Respostas

Felagund

a conexão deve estar sendo fechada antes, de uma verificada aonde vc fecha cada conexão.

M

Opa, o codigo do metodo receber esta assim:

public String receber() throws IOException {
	String x = null;
	x = dataIn.readUTF();
	System.out.println("Recebido"+x);
	//dataIn.close();
	return x;
	}

Depois que eu comentei o dataIN.close(); ele deu outro erro, que é o seguinte:

Exception in thread "Thread-1" java.lang.NullPointerException
	at Remota.receber(Remota.java:146)
	at recebeThread.run(recebeThread.java:30)
	at java.lang.Thread.run(Unknown Source)

Linha 30:

public void run(){
try {
	//System.out.println("Thread2");
	x = r.receber(); --LINHA 30
	if (x!=null){
               System.out.println("recebido"+x);

LINHA 146:

public String receber() throws IOException {
	String x = null;
	x = dataIn.readUTF();---LINHA 146
	System.out.println("Recebido"+x);
	//dataIn.close();
	return x;
	}

Ja tentei de tudo e nada =/.

Agora duas duvidas de iniciante mesmo.

1-Eu sempre tenho que fechar(close) a conexao no cliente?
2-Eu posso criar 2 metodos, um para iniciarservidor e outro para conectarcliente?pois todos os exeplos que vi na net eram com 2 classes distintas (servidor e cliente) e ambas possuiam o metodo main, enquanto na minha aplicação implementei uma classe Remota e nela possui os 2 metodos para iniciar ambos(ja q serei servidor e cliente).

Agradeço a atençao.

Marky.Vasconcelos

Voce tem que deixar a conexão aberta até não querer mais se comunicar com o cliente.

Poste o código inteiro do servidor e do cliente.

O que pode acontecer é que na incialização e na conexão é preciso obter os streams na ordem certa…
Mande o codigo para analizarmos melhor.

M

Segue o codigo.

Classe Remota onde inicio o cliente e servidor, além dos metodos enviar() e receber().

public Remota(String ip, int porta,ArrayList<String> ar, LeituraArquivo ler) throws IOException {
    	super();
        this.ip = ip;
        this.porta = porta;     
        
   
        Socket socket = iniciarCliente(ip,porta);
        if (socket == null) {
            socket = iniciarServidor(porta);
        }
          
    }
    
    public Socket iniciarServidor(int porta) throws IOException{
    	ServerSocket socket = null;
        Socket s = null;
		try{
		while (true) {
			socket = new ServerSocket(porta);
			System.out.println("Servidor Criado - Aguardando conexao...");
	    	System.out.println(socket);
	    	
	    	    	
	    	s = socket.accept();
	    	System.out.println("Cliente Conectou");
			InputStream in = s.getInputStream();
			dataIn = new DataInputStream(in);
						
    }	
       
    } catch (UnknownHostException ex) {
    	ex.printStackTrace();
    } catch (IOException ex) {
    	ex.printStackTrace();
    }
		return s;
    		
 }
    
    public Socket iniciarCliente(String ip,int porta) throws UnknownHostException, IOException{
    	Socket socket = null;
		
		try{
			socket = new Socket(ip, porta);
			OutputStream out = socket.getOutputStream();
			dataOut = new DataOutputStream(out);
            System.out.println("Cliente conectado");
            System.out.println(socket);
        
            	
    		socket.close();
            
        } catch (UnknownHostException ex) {
        } catch (IOException ex) {
        }
        
        return socket;

		}

Metodos enviar e receber:

public void enviar(String string throws IOException{
			if(golpe!=null){
				System.out.println(dataOut+"Saiu "+string);
				
				dataOut.writeUTF(string);
				System.out.println(dataOut+"Saiu "+string);
			}
	}

	
	public String receber() throws IOException {
				String x = null;
				x = dataIn.readUTF();
				System.out.println("Recebido"+x);
				//dataIn.close();
			return x;
	}
	    
}

Esse Metodos ENVIAR E RECEBER é chamado por 2 threads (uma trata o envio, outra o recebimento) que apontam para a classe REMOTA.

Agradeço sempre a atençao de vocês.

Abraço!

Marky.Vasconcelos

Voce ta criando um ServerSocket a cada loop… e não esta certo.

Isso…

while (true) {  
         socket = new ServerSocket(porta);

Deveria ser…

socket = new ServerSocket(porta);  
 while (true) {
Marky.Vasconcelos

Ahh… no método iniciarCliente depois de conectar voce esta fechando a conexão.

M

Opa, vou testar quando chegar em casa.

Agradeço a atenção d+.

Agora so mais uma duvida de iniciante… quando devo fechar a conexão?quando eu realmente devo da um socket.close();?

Forte abraço a todos.

M

Fiz o que voce pediu e deu o mesmo erro de antes.

Exception in thread "Thread-1" java.lang.NullPointerException
	at Remota.receber(Remota.java:145)
	at recebeThread.run(recebeThread.java:30)
	at java.lang.Thread.run(Unknown Source)

LINHA 30

public void run(){   
try {   
    //System.out.println("Thread2");   
    x = r.receber(); --LINHA 30   
    if (x!=null){   
               System.out.println("recebido"+x);

LINHA 146

public String receber() throws IOException {
				String x = null;
				x = dataIn.readUTF(); --LINHA 146
				System.out.println("Recebido"+x);
				//dataIn.close();
			return x;

ps: Ja testei com dataIn.close() com E sem comentario =/.

Aguardo mais opinioes.

Forte abraço!

Marky.Vasconcelos

Tente isso.

public Remota(String ip, int porta,ArrayList<String> ar, LeituraArquivo ler) throws IOException {
    	super();
        this.ip = ip;
        this.porta = porta;     
        
   
        Socket socket = iniciarCliente(ip,porta);
        if (socket == null) {
            socket = iniciarServidor(porta);
        }
          
    }
    
    public Socket iniciarServidor(int porta) throws IOException{
    	ServerSocket socket = null;
        Socket s = null;
		try{
                socket = new ServerSocket(porta);
	        System.out.println("Servidor Criado - Aguardando conexao...");
	    	System.out.println(socket);
		while (true) {
	    	s = socket.accept();
	    	System.out.println("Cliente Conectou");
		InputStream in = s.getInputStream();
		dataIn = new DataInputStream(in);				
                }	
       
    } catch (UnknownHostException ex) {
    	ex.printStackTrace();
    } catch (IOException ex) {
    	ex.printStackTrace();
    }
		return s;
    		
 }
    
    public Socket iniciarCliente(String ip,int porta) throws UnknownHostException, IOException{
    	Socket socket = null;
		
		try{
			socket = new Socket(ip, porta);
			OutputStream out = socket.getOutputStream();
			dataOut = new DataOutputStream(out);
            System.out.println("Cliente conectado");
            System.out.println(socket);
      
        } catch (UnknownHostException ex) {
        } catch (IOException ex) {
        }
        
        return socket;

		}

Os métodos enviar e receber

public void enviar(String string) throws IOException{
			if(golpe!=null){
				System.out.println(dataOut+"Saiu "+string);
				
				dataOut.writeUTF(string);
				System.out.println(dataOut+"Saiu "+string);
			}
	}

	
	public String receber() throws IOException {
				String x = null;
				x = dataIn.readUTF();
				System.out.println("Recebido"+x);
			return x;
	}
	    
}

Mas o correto seria ter o seu ServerSocket e as conexões aceitas serem enviadas para outra Thread.

Vou ver se faço algo aqui para te mostrar.

Marky.Vasconcelos

Exemplo pra voce…
Rode a classe Server uma vez… ela iniciara a escutar a porta para ler os sockets e enviar para o handler.

Depois rode o cliente… voce vera que ele se comunicara com o server depois fechara a conexão. Mas o server continua ouvindo. Rode o cliente quantas vezes quiser para o mesmo server.

Entenda depois tente implementar no seu modelo.

Classe Server:

package br.ex;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	public Server() {
		try {
			ServerSocket socket = new ServerSocket(5000);
			while (true)
				new SocketHandler(socket.accept()).start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static class SocketHandler extends Thread {
		private Socket socket;

		public SocketHandler(Socket socket) {
			this.socket = socket;
		}

		public void run() {
			try {
				ObjectOutputStream out = new ObjectOutputStream(socket
						.getOutputStream());
				ObjectInputStream in = new ObjectInputStream(socket
						.getInputStream());
				for (int i = 0; i < 10; i++) {
					String clienteMsg = (String) in.readObject();
					System.out.println(clienteMsg);
					out.writeObject("Resp:" + i);
				}
				in.close();
				out.close();
				socket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		new Server();
	}
}

Classe Cliente

package br.ex;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Cliente {
	public Cliente() {
		try {
			Socket socket = new Socket("127.0.0.1", 5000);
			ObjectInputStream in = new ObjectInputStream(socket
					.getInputStream());
			ObjectOutputStream out = new ObjectOutputStream(socket
					.getOutputStream());
			for (int i = 0; i < 10; i++) {
				out.writeObject("Loop: " + i);
				String resp = (String) in.readObject();
				System.out.println(resp);
			}
			out.close();
			in.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new Cliente();
	}
}
M

Blz, Mark.

Mto obrigado pela ajuda, vou da uma sacada ae.

Acho que também tem o lance de eu ser cliente e servidor, então pela lógica, teria que pedir para iniciar 1º o cliente dae ele teria que retornar um booleano indicando se conseguiu conectar no servidor ou não, caso não consiga ai ja peço para iniciar o servidor. (Pois o mesmo codigo sera executado tanto no cliente quanto no servidor, entendeu?).
Com isso tanto o cliente quanto o servidor enviará strings entre um e outro.

Forte abraço!

M

Tentei fazer o que você pediu no codigo acima(No codigo que vc refez no meu).

Realmente parece erro de threads, o servidor é criado direitim(como antes), qnd o cliente conecta aparece a msg “cliente conectou” de boa… mas retorna o erro anterior.

Exception in thread "Thread-1" java.lang.NullPointerException
	at Remota.receber(Remota.java:142)
	at recebeThread.run(recebeThread.java:30)
	at java.lang.Thread.run(Unknown Source)

Vo tentar estudar o seu codigo acima para implementar no meu.

Abraço!

Marky.Vasconcelos

Ahh… se eu fosse voce eu criaria uma classe pra cada.

M

Agradeço mais uma vez a enorme a atenção.

Só mais uma dúvida, o ip e a porta do servidor eu terei que ler em um arquivo .txt, onde fica os dados da conexão… até ai tudo bem pois ja implementei isso.

O que eu gostaria de saber é como o outro pc(no caso o cliente) vai saber o ip do servidor?

Forte abraço

Marky.Vasconcelos

http://www.meuip.com.br/
Entre e veja seu numero de ip.
É o ip que o cliente vai colocar.

Se o servidor tiver usando uma conexão com a internet roteada as coisas complicam um pouquinho mais.

B

No meu caso é meio parecido com o dele.
estou criando um Chat.
So que não estou entrando com valores via teclado.

Criei um ambiente gráfico em Jframe. e estou entrando no Cliente com uma String em um Jtext.
Obrigado.

try{
        Socket conexao=new Socket("127.0.0.1", 8081);
        DataOutputStream out= new DataOutputStream(conexao.getOutputStream());
        out.writeUTF("nome: "+Textnome.getText()+"\nsetor: "+Textsetor.getText()+"\ndata: "+Textdata.getText()+"\nmensagem: "+Textareasolicitacao.getText());
        out.close();
        conexao.close();
    }catch(Exception e){
    }
B

ajuda?

Criado 30 de março de 2009
Ultima resposta 3 de jun. de 2010
Respostas 17
Participantes 4