从Socket多次打开读/写流

Kus*_*hal 4 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是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 Code Online (Sandbox Code Playgroud)

run()方法ClientHandler.

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();
}
Run Code Online (Sandbox Code Playgroud)

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

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();
}
Run Code Online (Sandbox Code Playgroud)

您可能已经注意到,在连接后确认客户端后,我关闭读/写流,并从服务客户端的新线程,我再次打开流,并从服务器读取/写入连接套接字已启动,但是一旦我尝试在Hello!客户端发送时读取服务器的响应,它就会崩溃EOFException而不是获取success.

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

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

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

Lai*_*Chu 5

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

关闭Ob​​jectInputStream时,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();
}
Run Code Online (Sandbox Code Playgroud)

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