Socket的PrintWriter在关闭之前不会发送

时间:2017-08-14 22:42:14

标签: java sockets networking

我的客户端代码如下:

Socket s = new Socket(server.getHostName(), server.getPort());
PrintWriter p = new PrintWriter(s.getOutputStream());
p.println(message);
p.flush();
s.shutdownOutput();

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String newLine;
StringBuffer response = new StringBuffer();
while((newLine = br.readLine()) != null)
    response.append(newLine);
System.out.println(response.toString());
p.close();
br.close();

和服务器代码如下:

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String nextLine;
StringBuffer request = new StringBuffer();

System.out.println("Starting read....");
String nextline;
while((nextline = br.readLine()) != null){
    System.out.println(nextline);
    request.append(nextline);
}
System.out.println("Message recived!!");
System.out.println("Request: " + request);

PrintWriter p = new PrintWriter(s.getOutputStream());
p.println("Hello, fileclient!");
System.out.println("Message sent!!");

p.close();
br.close();

在我放行s.shutDownInput()之前,服务器代码会挂起br.readLine().我设法修复的方法是关闭PrintWriter一些方法,通过p.close()或者通过目前没有的方式 关闭套接字就像关闭PrintWriterp.close()一样。之后,客户端和服务器之间的交互是完美的。

为什么PrintWriterBufferedReaderPrintWriter以某种方式关闭之前不会发送/接收?

2 个答案:

答案 0 :(得分:1)

它与PrintWriter没有任何关系。这是您的应用程序协议错误。

  • 服务器循环读取行直到流结束。

  • 客户端正在发送一行,然后没有关闭套接字,因此没有发送流末尾(直到您添加了关闭)。

  • 服务器正在响应。

  • 然后客户正在阅读。

因此,在服务器退出循环之前,客户端不会读取任何内容,并且服务器没有退出循环,因为客户端正在读取未关闭。

所以下定决心。可能服务器应该只读一行。

答案 1 :(得分:1)

双方的行为完全按照你的要求去做。特别是,在指派任何响应之前,您将指示服务器专门读取客户端发送的所有内容:

    String nextline;
    while((nextline = br.readLine()) != null){
        System.out.println(nextline);
        request.append(nextline);
    }

重要的是要理解,在 stream 的错误或结束之前不会停止读取,其中套接字上的流结束对应于已关闭的另一端并且已读取所有数据。换句话说,在分派响应之前,您的服务器会等待整个会话的结束,而不是单个消息的结束。

由于这显然不是您想要的,因此您需要在服务器上实施不同的策略,以确定何时处理到目前为止收到的数据并发送响应。如果您确信自己的邮件不会包含内部换行符,那么这可能就像服务器在发送每个回复之前只执行一个 br.readLine()一样简单。