从Socket多次打开读/写流

时间:2012-06-09 16:45:30

标签: java sockets

在我有ServerSocket侦听传入连接的类中,以下是代码:

while(isRunning)
{
    try
    {
        Socket s = mysocketserver.accept();
        acknowledgeClient(s);
        new ClientHandler(s).start(); //Start new thread to serve the client, and get back to accept new connections.
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}

以下是acknowledgeClient(Socket s)代码。

ObjectInputStream in = new ObjectInputStream(s.getInputStream);
ObjectOutputStream out = new ObjectOutputStream(s.getOutStream);
String msg = in.readObject().toString();
System.out.println(msg+" is Connected"); //Show who's connected
out.writeObject("success"); //Respond with success.
in.close();
out.close();

run()的{​​{1}}方法。

ClientHandler

以下是客户端程序与此Echo Server通信的方式。

try
{
    in = new ObjectInputStream(client.getInputStream());
    out = new ObjectOutputstream(client.getOutputStream());
    String msg = "";
    while(!msg.equalsIgnoreCase("bye"))
    {
        msg = in.readObject().toString();
        System.out.println("Client Says - "+msg);
        out.writeObject("success");
    }
    in.close();
    out.close();
}
catch(Exception ex)
{
    ex.printStackTrace();
}

您可能已经注意到,在连接后确认客户端之后,我关闭读/写流,并从服务客户端的新线程,我再次打开流,并从服务器读取/从连接的套接字开始写入,但是一旦我尝试通过客户端发送try { int count = 10; client = new Socket("localhost",8666); in = new ObjectInputStream(client.getInputStream()); out = new ObjectOutputstream(client.getOutputStream()); out.writeObject("Foo"); System.out.println("Connection Status : "+in.readObject().toString()); while(count>0) { out.writeObject("Hello!"); String resp = in.readObject().toString(); //Getting EOFException here. System.out.println("Sent with :"+resp); count--; Thread.sleep(1000); } out.close(); in.close(); client.close(); } catch(Exception ex) { ex.printStackTrace(); } 时读取服务器的响应,它就会与Hello!崩溃而不是EOFException

我知道发生EOF的原因但是没有得到它为什么会发生在这里的线索,我不是在尝试读取其流中没有任何内容的套接字(它应该由服务器写的success )。

在服务器在其末尾打印success并将Hello!写为响应之前,客户端是否尝试读取套接字是否为时尚早?

P.S。 :我知道通过提供如此多的代码来问问题不是一个好方法,我们期望在这里获得问题的答案并理解它,而不是让我们的问题由其他人解决并逃脱。所以,我提供了这么多代码来展示问题的所有方面。

4 个答案:

答案 0 :(得分:5)

我研究了ObjectInputStream的源代码,看来对原始输入流s.getInputStream()的引用存储在ObjectInputStream中。

关闭ObjectInputStream时,s.getInputStream()也会关闭。

输入流关闭后,无法再次打开。因此,您会收到一个EOFException,表示您位于流的末尾(因为无法再次打开流)。

你应该做这样的事情来承认客户。

在ClientHandler的run()方法中:

try {
    // acknowledge client
    ObjectInputStream in = new ObjectInputStream(s.getInputStream());
    ObjectOutputStream out = new ObjectOutputStream(s.getOutStream());
    String msg = in.readObject().toString();
    System.out.println(msg+" is Connected"); //Show who's connected
    out.writeObject("success"); //Respond with success.
    // end acknowledge client

    String msg = "";
    while(!msg.equalsIgnoreCase("bye"))
    {
        msg = in.readObject().toString();
        System.out.println("Client Says - "+msg);
        out.writeObject("success");
    }
    in.close();
    out.close();
}
catch(Exception ex)
{
    ex.printStackTrace();
}

如果要在单独的方法中隔离确认代码,只需确保在不关闭流的情况下保持对同一ObjectInputStream的正确引用,然后传递引用。

答案 1 :(得分:1)

  

我再次打开流,然后从服务器读取/写入已连接的套接字,

关闭流后,您无法再次打开它。实际上,你不能以这种方式在同一个流上使用两个Object流。

相反,您应该为输入和输出创建一次对象流,只打一次,直到完成后才关闭它。

答案 2 :(得分:0)

好好看看这个程序,我把它写成了解多个客户端和服务器通信,你的问题在这个程序中得到了解答。

客户端代码

public class ClientWala {

    public static void main(String[] args) throws Exception{

        Boolean b = true;
    Socket s = new Socket("127.0.0.1", 4444);

    System.out.println("connected: "+s.isConnected());


    OutputStream output = s.getOutputStream();
    PrintWriter pw = new PrintWriter(output,true);

    // to write data to server
    while(b){

        if (!b){

             System.exit(0);
        }

        else {
            pw.write(new Scanner(System.in).nextLine());
        }
    }


    // to read data from server
    InputStream input   = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(input);
    BufferedReader br = new BufferedReader(isr);
    String data = null;

    while ((data = br.readLine())!=null){

        // Print it using sysout, or do whatever you want with the incoming data from server

    }




    }
}

服务器端代码

public class ServerTest {

    ServerSocket s;

    public void go() {

        try {
            s = new ServerSocket(44457);

            while (true) {

                Socket incoming = s.accept();
                Thread t = new Thread(new MyCon(incoming));
                t.start();
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    class MyCon implements Runnable {

        Socket incoming;

        public MyCon(Socket incoming) {

            this.incoming = incoming;
        }

        @Override
        public void run() {

            try {
                PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                        true);
                InputStreamReader isr = new InputStreamReader(
                        incoming.getInputStream());
                BufferedReader br = new BufferedReader(isr);
                String inp = null;

                boolean isDone = true;

                System.out.println("TYPE : BYE");
                System.out.println();
                while (isDone && ((inp = br.readLine()) != null)) {

                    System.out.println(inp);
                    if (inp.trim().equals("BYE")) {
                        System.out
                                .println("THANKS FOR CONNECTING...Bye for now");
                        isDone = false;
                        s.close();
                    }

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    s.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new ServerTest().go();

    }

}

答案 3 :(得分:0)

关闭套接字流周围的任何输入流或输出流或读取器或写入器会关闭套接字,并暗示其他流,读取器和编写器。

在套接字的生命周期中使用相同的流,读者和编写器。