2011-12-04 10 views
7


jestem programowania klasę do komunikowania się z serwerem, ale gdy próbuje skonstruować ObjectInputStream z pomocą InputStream program zamrażania. Nie jest to wyjątek, a program nadal działa, ale zawieszony w linii, w której próbuje utworzyć obiekt ObjectInputstream.ObjectInputStream (socket.getInputStream()); nie działa

Herezje kod metody gdzie mój problem jest zlokalizowany:

@Override 
public void connect(String ip, int port) throws UnknownHostException, IOException { 
    Socket socket = new Socket(ip, port); 
    out = new ObjectOutputStream(socket.getOutputStream()); 
    InputStream is = socket.getInputStream(); 
    in = new ObjectInputStream(is); 
} 

i jest to kod dla całej klasy:

package Client; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.PrintWriter; 
import java.net.Socket; 
import java.net.UnknownHostException; 


public class MessageStreamerImpl implements MessageStreamer { 
    ObjectOutputStream out; 
    ObjectInputStream in; 

    public MessageStreamerImpl(String ip, int port) throws UnknownHostException, IOException{ 
     connect(ip, port); 
    } 

    public MessageStreamerImpl(){ 
    } 

    @Override 
    public void send(Object message) throws IOException { 
     if(out == null) throw new IOException(); 
     out.writeObject(message); 
     out.flush(); 
    } 

    @Override 
    public Object receive() throws IOException{ 
     try { 
      return in.readObject(); 
     } catch (ClassNotFoundException e) { 
      throw new IOException(); 
     } 
    } 

    @Override 
    public void connect(String ip, int port) throws UnknownHostException, IOException { 
     Socket socket = new Socket(ip, port); 
     out = new ObjectOutputStream(socket.getOutputStream()); 
     InputStream is = socket.getInputStream(); 
     in = new ObjectInputStream(is); 
    } 

} 

Patrząc na Google znalazłem to: http://www.coderanch.com/t/232944/threads/java/Socket-getInputStream-block. Ale nadal nie wiem, jak rozwiązać problem, ponieważ mój konstruktor ObjectOutputStream jest wcześniejszy niż ObjectInputStream.

Oto mój kod serwera, może to pomoże;)

package Server; 

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.SocketException; 
import java.util.ArrayList; 

public class Server { 
    ArrayList<Socket> clients = new ArrayList<Socket>(); 

    public Server(int port){ 
     try { 
      ServerSocket mySocket = new ServerSocket(port); 
      waitForClients(mySocket); 
     } catch (IOException e) { 
      System.out.println("Unable to start."); 
      e.printStackTrace(); 
     } 
    } 

    private void waitForClients(ServerSocket mySocket) { 
     while(true){ 
      try { 
       System.out.println("Ready to receive"); 
       Socket client = mySocket.accept(); 
       clients.add(client); 
       System.out.println(client.getInetAddress().getHostAddress()+" connected to the Server"); 
       Thread t = new Thread(new ClientHandler(client)); 
       t.start(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    public void shareToAll(Object objectToSchare){ 
     for(Socket client:clients){ 
      ObjectOutputStream oos; 
      try { 
       oos = new ObjectOutputStream(client.getOutputStream()); 
       oos.writeObject(objectToSchare); 
       oos.close(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    private class ClientHandler implements Runnable{ 
     Socket clientSocket; 

     public ClientHandler(Socket clientSocket){ 
      this.clientSocket = clientSocket; 
     } 
     @Override 
     public void run() { 
      try { 
       ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream()); 
       while(true){ 
        try { 
         ois.readObject(); 

        } catch (ClassNotFoundException | IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
      }catch(SocketException e){ 
       System.out.println(clientSocket.getInetAddress().getHostAddress()+" disconnected from the Server"); 
       clients.remove(clientSocket); 
      }catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Dzięki za pomoc znalazłem usterkę. To właśnie w klasie serwera, który musi wyglądać następująco:

package Server; 

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.SocketException; 
import java.util.ArrayList; 

public class Server { 
    ArrayList<ObjectOutputStream> clientstreams = new ArrayList<ObjectOutputStream>(); 

    public Server(int port){ 
     try { 
      ServerSocket mySocket = new ServerSocket(port); 
      waitForClients(mySocket); 
     } catch (IOException e) { 
      System.out.println("Unable to start."); 
      e.printStackTrace(); 
     } 
    } 

    private void waitForClients(ServerSocket mySocket) { 
     while(true){ 
      try { 
       System.out.println("Ready to receive"); 
       Socket client = mySocket.accept(); 
       clientstreams.add(new ObjectOutputStream(client.getOutputStream())); 
       System.out.println(client.getInetAddress().getHostAddress()+" connected to the Server"); 
       Thread t = new Thread(new ClientHandler(client)); 
       t.start(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    public void shareToAll(Object objectToSchare){ 
     for(ObjectOutputStream stream:clientstreams){ 
      try { 
       stream.writeObject(objectToSchare); 
       stream.flush(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    private class ClientHandler implements Runnable{ 
     Socket clientSocket; 

     public ClientHandler(Socket clientSocket){ 
      this.clientSocket = clientSocket; 
     } 
     @Override 
     public void run() { 
      try { 
       ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream()); 
       while(true){ 
        try { 
         ois.readObject(); 

        } catch (ClassNotFoundException | IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
      }catch(SocketException e){ 
       System.out.println(clientSocket.getInetAddress().getHostAddress()+" disconnected from the Server"); 
       clientstreams.remove(clientSocket); 
      }catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Najwięcej zmian można zobaczyć na waitForClients metoda(), ale zmienił się też koncepcja mojego ArrayList i metoda shareToAll.

Odpowiedz

12

konstruktor ObjectInputStream odczytuje dane z danego InputStream. Aby to działało, to musi natychmiast przepłukać ObjectOutputStream po constuction (napisać początkowy nagłówek) przed próbą otwarcia ObjectInputStream. Także, jeśli chcesz wysłać więcej niż jeden obiekt na połączenie, należy otworzyć ObjectOutputStream raz i używać go przez cały okres gniazda (na przykład metodę shareToAll).

+0

ja nie wiem, czy miał to samo, ale znalazłem przyczynę. Faul się w klasie serwera w waitForClients() w trzeba wygenerować OutputStream po gniazdami = mySocket.accept(); za pomocą client.getOutputstream() ;. W przeciwnym razie Klient jest zablokowany czekając na OutputStream (jego InputStream). Dziękuję –

+0

Edytowałem pytanie, ponieważ nie mogę jeszcze odpowiadać na moje pytania. –

+0

nadal nie powinieneś za każdym razem redefiniować strumieni wejściowych i wyjściowych. Powinny one być globalne w klasie 'ClientHandler'. – Jon