ObjectInputStream(socket.getInputStream());不工作

Posted

技术标签:

【中文标题】ObjectInputStream(socket.getInputStream());不工作【英文标题】:ObjectInputStream(socket.getInputStream()); does not work 【发布时间】:2012-01-12 17:16:32 【问题描述】:

我正在编写一个与服务器通信的类,但是当它尝试在输入流的帮助下构造 ObjectInputStream 时,程序会冻结。没有异常,程序仍在运行,但挂在尝试构造 ObjectInputstream 的行中。

这是我的问题所在方法的代码:

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

这是整个班级的代码:

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


在查看 Google 时,我发现了这个:http://www.coderanch.com/t/232944/threads/java/Socket-getInputStream-block。但是我仍然不知道如何解决这个问题,因为我的 ObjectOutputStream 构造函数在 ObjectInputStream 之前。

这是我的服务器代码,也许会有所帮助;)

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

感谢您的帮助,我找到了问题所在。它在服务器类中,必须如下所示:

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

您在方法 waitForClients() 中看到的变化最多,但我也改变了 ArrayList 和 shareToAll 方法的概念。

【问题讨论】:

【参考方案1】:

ObjectInputStream 构造函数从给定的 InputStream 中读取数据。为了使其工作,您必须在构造后立即刷新 ObjectOutputStream(以写入初始标头),然后再尝试打开 ObjectInputStream。此外,如果您想在每个连接中发送多个对象,则必须打开一次 ObjectOutputStream 并在套接字的整个生命周期内使用它(例如,您的 shareToAll 方法)。

【讨论】:

不知道你是不是也这样,但是我找到了原因。错误出现在方法 waitForClients() 的服务器类中,我必须在 Socket client = mySocket.accept(); 之后生成一个输出流与 client.getOutputstream();.否则客户端被阻塞等待OutputStream(他的InputStream)。谢谢 我编辑了这个问题,因为我还不能回答我自己的问题。 您仍然不应该每次都重新定义输入和输出流。它们应该在 ClientHandler 类中是全局的。 他们是。或者他们几乎是......但我现在只建造一次。输出流现在在我的 Arraylist 中表示,输入流在我的 ClientHandler 中的 while 循环之前被定义一次;)

以上是关于ObjectInputStream(socket.getInputStream());不工作的主要内容,如果未能解决你的问题,请参考以下文章

Java 创建一个新的 ObjectInputStream 块

java socket长连接

Socket网络编程错误

DAY16第十六天Socket套接字学习笔记

通过socket java向多个客户端广播对象

java.io.StreamCorruptedException: invalid stream header: 0008493A