Java 插座';s PrintWriter没有';在关闭之前不要发送

Java 插座';s PrintWriter没有';在关闭之前不要发送,java,sockets,networking,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.getIn

我的客户端代码如下所示:

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();
和服务器代码,如下所示:

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()。
我设法解决的方法是通过
p.close()
或通过当前不可用的方式关闭
PrintWriter
关闭套接字,就像通过
p关闭
PrintWriter
一样。关闭()
。之后,客户端和服务器之间的交互就完美了


为什么
PrintWriter
BufferedReader
PrintWriter
关闭之前不发送/接收?

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

  • 服务器正在循环读取行,直到流结束

  • 客户端正在发送一行数据,但没有关闭套接字,因此没有发送流的结尾(直到您添加关机)

  • 然后服务器会做出响应

  • 客户正在阅读

因此,在服务器退出循环之前,客户端不会读取任何内容,服务器也不会退出其循环,因为客户端正在读取而不是关闭


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

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

  • 服务器正在循环读取行,直到流结束

  • 客户端正在发送一行数据,但没有关闭套接字,因此没有发送流的结尾(直到您添加关机)

  • 然后服务器会做出响应

  • 客户正在阅读

因此,在服务器退出循环之前,客户端不会读取任何内容,服务器也不会退出其循环,因为客户端正在读取而不是关闭


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

双方的行为都与您告诉他们的完全一致。特别是,您特别指示服务器在发送任何响应之前读取客户端发送的所有内容:

    String nextline;
    while((nextline = br.readLine()) != null){
        System.out.println(nextline);
        request.append(nextline);
    }
重要的是要理解,直到出现错误或流结束时才会停止读取,其中套接字上的流结束对应于另一端已关闭且所有数据已读取。换句话说,您的服务器等待整个会话结束,而不是单个消息结束,然后再发送响应


因为这显然不是您想要的,所以您需要在服务器上实现不同的策略,以确定何时处理到目前为止接收到的数据并发送响应。如果您确信您的消息不会包含内部换行符,那么这可能很简单,因为服务器在发送每个响应之前只执行一个
br.readLine()

双方的行为与您告诉他们的完全一样。特别是,您特别指示服务器在发送任何响应之前读取客户端发送的所有内容:

    String nextline;
    while((nextline = br.readLine()) != null){
        System.out.println(nextline);
        request.append(nextline);
    }
重要的是要理解,直到出现错误或流结束时才会停止读取,其中套接字上的流结束对应于另一端已关闭且所有数据已读取。换句话说,您的服务器等待整个会话结束,而不是单个消息结束,然后再发送响应


因为这显然不是您想要的,所以您需要在服务器上实现不同的策略,以确定何时处理到目前为止接收到的数据并发送响应。如果您确信您的邮件不会包含内部换行符,那么这可能很简单,因为服务器在发送每个响应之前只执行一个?缓冲是正常的,关闭流会迫使它刷新其内容。我猜他希望保持套接字打开,以便能够发送更多数据。正如现在的一个注意事项,您应该使用try with resources自动正确地关闭资源,如
socket
s。它看起来是这样的:
try(sockets=newsocket(…){your code}
。Java现在在到达末尾时自动关闭
try(…)
部分中定义的所有资源(关闭
}
)。这可以通过实现
AutoCloseable
的所有类来实现:@Zabuza谢谢,我提供了与问题相关的代码。在实际的程序中,我使用了try-with-resources。你为什么期望它这样做?缓冲是正常的,关闭流会迫使它刷新其内容。我猜他希望保持套接字打开,以便能够发送更多数据。正如现在的一个注意事项,您应该使用try with resources自动正确地关闭资源,如
socket
s。它看起来是这样的:
try(sockets=newsocket(…){your code}
。Java现在在到达末尾时自动关闭
try(…)
部分中定义的所有资源(关闭
}
)。这可以通过实现
AutoCloseable
的所有类来实现:@Zabuza谢谢,我提供了与问题相关的代码。在实际的程序中,我使用了try-with-resources。您和@John Bollinger都是正确的。我不知道br.readLine()一直读到流的末尾。我以为它一直持续到没有更多的台词可读为止。非常感谢你!对于未来的人,阅读直到br.readLine()等于null,或者如果它接收到并使用单个“q”。将记录
readLine()
的行为。它直到流结束时才读取,但您的代码会这样做,通过循环直到返回null,这是在流结束时执行的。您和@John Bollinger都是正确的。我不知道br.readLine()是