【发布时间】:2019-03-19 12:17:36
【问题描述】:
我正在尝试用 Java 实现一个简单的 http 服务器,以了解 http 服务器是如何工作的。现在,我可以从任何浏览器发送请求并收到正确的响应,但是,当我尝试模拟来自 Postman 的请求时,它总是抛出 java.net.SocketException: Broken pipe (Write failed) 异常。
我的 http 服务器很简单:一旦收到请求,就向发送者回显消息。
实现如下,Source Code
package com.ont.http;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SingleThreadHttpServer implements HttpServer {
public void run(int port) throws IOException {
ServerSocket serverSocket = new ServerSocket(port);
try {
while (true) {
Socket socket = serverSocket.accept();
BufferedReader inBufferReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder stringBuffer = new StringBuilder();
String inputLine;
while ((inputLine = inBufferReader.readLine()) != null && !inputLine.equals("")) {
stringBuffer.append(inputLine);
stringBuffer.append("\r\n");
}
System.out.println(stringBuffer.toString());
OutputStream outStream = socket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new StringReader("A Message from server."));
// Header should be ended with '\r\n' at each line.
outStream.write("HTTP/1.1 200 OK\r\n".getBytes());
outStream.write("Main: OneServer 0.1\r\n".getBytes());
outStream.write("Content-length: 22\r\n".getBytes()); // if text/plain the length is required
outStream.write("Content-Type: text/plain\r\n".getBytes());
// An empty line is required after the header
outStream.write("\r\n".getBytes());
String line;
while ((line = bufferedReader.readLine()) != null) {
outStream.write(line.getBytes());
}
inBufferReader.close();
bufferedReader.close();
outStream.flush();
outStream.close(); // Socket will close automatically once output stream is closed.
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
从 Postman 发送的任何类型的请求都会立即触发该异常,并且 debug 会告诉您在outStream.write(...) 期间套接字连接已丢失。如果我从浏览器发送,它永远不会触发该问题。
我不明白的是,不应该对 Postman 应用任何设置,因为当我尝试模拟对我的 tomcat 的请求时,它会像魅力一样处理所有事情,我的一定有问题代码,但我不知道在哪里以及为什么。
任何帮助或提示将不胜感激,谢谢。
----- 更新----
从 Postman 控制台,我可以看到这个异常,
Error: read ECONNRESET
Request Headers:
accept:"text/plain"
cache-control:"no-cache"
如果我只留下outStream.write("HTTP/1.1 200 OK\r\n".getBytes()) 这一行,并删除所有其他outStream.write...,浏览器和邮递员都会像魅力一样工作。这真是拉扯我的头发,但是为什么呢?
【问题讨论】:
-
邮递员请求是否说它接受
text/plain?我怀疑它没有,然后它会看到标头并关闭请求。 -
@BoristheSpider 谢谢,但我不认为这是问题所在,因为如果你不指定它的接受,邮递员会接受 /。
-
您的 HTTP 响应缺少
Connection: close标头,以让客户端知道在发送响应后连接将被有意关闭。此外,Content-length应该是Content-Length。而且您没有指出 哪个 调用outStream.write()是引发异常的那个。 -
你是对的,有一个错字,但是我试过
Content-length和Content-Length没有区别,而且outStream.write("HTTP/1.1 200 OK\r\n".getBytes());这个调用之后出现异常,不管是哪一种将其他outStream.write(...)的订单放在此行之后,它会引发相同的异常。这意味着我只能将所有内容放在一行中,然后在第一次outStream.write()调用后关闭连接。
标签: java sockets postman serversocket httpserver