我在 Java 中搞乱了 HTTP 和套接字,希望你能对此有所了解:
当我用 Java SE 11 编写的 HTTP 服务器没有读取整个请求然后响应时,客户端不会收到它或收到错误。这是为什么?在服务器读取整个请求之前,客户端是否无法读取响应?如果在下面的代码片段中执行对 readBody 的调用,则效果很好。如果响应具有 Content-Length 标头和文本正文,它也可以正常工作。这其实更让我困惑。
我的示例请求是带有数据的 POSTfds。邮递员说“无法收到任何请求”,而curl说“curl:(56)接收失败:连接由对等方重置”。
import java.io.*;
import java.net.Socket;
import java.util.*;
class Handler {
public synchronized void read(Socket incoming) {
try (incoming;
OutputStream outputStream = incoming.getOutputStream();
InputStream inputStream = incoming.getInputStream();
PrintWriter pw = new PrintWriter(outputStream)) {
writeRequest(inputStream);
pw.print("HTTP/1.1 200 OK\r\n");
pw.print("\r\n");
pw.flush();
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage());
e.printStackTrace();
}
}
private void writeRequest(InputStream inputStream) throws IOException {
String verbLine = readLine(inputStream);
Map<String, String> headers = readHeaders(inputStream);
//readBody(inputStream, headers);
}
private void readBody(InputStream inputStream, Map<String, String> headers) throws IOException {
Optional<String> optKey = headers.keySet().stream()
.filter(k -> k.equalsIgnoreCase("Content-Length"))
.findFirst();
if (optKey.isPresent()) {
int contentLength = Integer.parseInt(headers.get(optKey.get()));
byte[] bytes = inputStream.readNBytes(contentLength);
}
}
private Map<String, String> readHeaders(InputStream inputStream) throws IOException {
Map<String, String> headers = new HashMap<>();
while (true) {
String line = readLine(inputStream);
if (line == null || line.isEmpty()) {
return headers;
}
String key = line.split(":")[0].trim();
String value = line.split(":")[1].trim();
headers.put(key, value);
}
}
private String readLine(InputStream inputStream) throws IOException {
byte[] buf = new byte[200];
int offset = 0;
while (true) {
int read = inputStream.read();
if (read == -1) {
return null;
}
buf[offset] = (byte) read;
if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) {
return "";
}
if (buf[offset] == 0x0A) {
int endOfLine = buf[offset - 1] == 0x0D ? offset - 1 : offset;
return new String(buf, 0, endOfLine);
} else {
offset++;
}
}
}
}
如果在服务器上仍有未读数据时关闭套接字,则会导致客户端发生连接重置错误。此处发生这种情况是因为您没有阅读完整的请求。如果尚未读取服务器的完整响应,则会向用户公开此错误。
如果您发送带有content-length
然后是完整的正文,然后客户端将读取完整的响应,因此错误将被忽略。如果您两者都不发送content-length
也不使用分块编码,客户端将期望响应以正确关闭 TCP 连接而结束。在这种情况下,连接重置将传播给用户,因为尚未(正确)读取来自服务器的完整响应。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)