2011-12-04 22 views
7


Tôi đang lập trình một lớp để giao tiếp với máy chủ nhưng khi nó cố gắng xây dựng ObjectInputStream với sự trợ giúp của luồng đầu vào chương trình bị đóng băng. Theres không có ngoại lệ và chương trình vẫn chạy nhưng treo trong dòng nơi nó cố gắng xây dựng ObjectInputstream.ObjectInputStream (socket.getInputStream()); không hoạt động

Heres mã của phương pháp mà vấn đề của tôi tọa lạc:

@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); 
} 

và đây là mã cho cả lớp:

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); 
    } 

} 

Trong khi tìm kiếm tại Google Tôi thấy điều này: http://www.coderanch.com/t/232944/threads/java/Socket-getInputStream-block. Nhưng tôi vẫn không biết làm thế nào để giải quyết vấn đề, bởi vì constructor ObjectOutputStream của tôi là trước một cho ObjectInputStream.

Đây là mã máy chủ của tôi, có lẽ nó sẽ giúp;)

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(); 
      } 
     } 
    } 
} 

Nhờ sự giúp đỡ của bạn tôi thấy lỗi. Đó là tại lớp máy chủ trong đó có xem xét như thế này:

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(); 
      } 
     } 
    } 
} 

Phần lớn thay đổi mà bạn nhìn thấy ở waitForClients() phương pháp nhưng tôi đã thay đổi, quá khái niệm về ArrayList của tôi và phương pháp shareToAll.

Trả lời

12

hàm tạo ObjectInputStream đọc dữ liệu từ InputStream đã cho. để làm việc này, bạn phải xóa ObjectOutputStream ngay sau khi kết thúc (để viết tiêu đề ban đầu) trước khi bạn cố gắng mở ObjectInputStream. Ngoài ra, nếu bạn muốn gửi nhiều hơn một đối tượng cho mỗi kết nối, bạn phải mở ObjectOutputStream một lần và sử dụng nó trong suốt thời gian của socket (ví dụ: phương thức shareToAll).

+0

Tôi không biết bạn có giống nhau hay không nhưng tôi đã tìm ra lý do. Các faul là trong lớp máy chủ tại phương thức waitForClients() Tôi phải tạo ra một Outputstream sau khi Socket client = mySocket.accept(); với client.getOutputstream() ;. Nếu không, Máy khách bị chặn chờ OutputStream (InputStream của anh ta). Cảm ơn bạn –

+0

Tôi đã chỉnh sửa câu hỏi vì tôi chưa được phép trả lời câu hỏi của riêng tôi. –

+0

bạn vẫn không nên xác định lại luồng đầu vào và đầu ra mỗi lần. Chúng phải là toàn cục bên trong lớp 'ClientHandler'. – Jon