【发布时间】:2017-11-04 14:10:22
【问题描述】:
我编写了使用 Sockets 的 Java 程序,以便从客户端接收 http 请求(请注意:一切都发生在 localhost 中),如果选择了 GET,我使用 Socket 库的程序会输出标头响应和 html 正文由客户。让我举个例子:
我在端口 12345 上运行我的服务器,我的源文件由 java 文件和示例 html 文件组成。
客户端,使用网络浏览器输入:http://localhost:12345/path-to-source/File.html
服务器通过 InputStream 获取输入:GET path-to-file/File.html HTTP/1.1
所以它通过 OutputStream 响应 HTTP 状态(200 OK),其他字段,如内容类型、内容长度,然后是正文(html 源代码)。
由于某种原因,它不会向浏览器输出任何内容。另一方面,当我使用终端并输入:
curl -s -I -X GET localhost:12345/path-to-file/File.html
它实际上向客户端显示正确的输出:
HTTP/1.1 200 OK
Host: localhost:12345
User-Agent: curl/7.51.0
Accept: */*
Content-Type: */*
Content-Length: 18900
但由于某种原因,Accept 是 / 事件,尽管我已经预料到 text/html
所以要清楚,我想要的输出是:
HTTP/1.1 200 OK
Accept: text/html
Content-Type: text/html
Content-Length: 18900
Content: .....
你能看看我的代码并找出我在这做错了什么吗?另外,我不想使用其他库,因为我想了解套接字的工作原理和低级别:
public class WebServerMain {/** This method prints to the output stream (to the client) the necessary fields, like Content type, Content length and etc.
It only serves GET and HEAD requests and if the file exists (200). **/
public static void printToClient(int length,BufferedReader in, PrintWriter out) {
String request;
String response;
try {
while ((request = in.readLine()) != null) {
out.println(request);
if (request.split(" ")[0].equals("Accept:")) {
response = request.split(" ")[1].split(",")[0];
out.print("Content-Type: " + response + "\r\n");
out.print("Content-Length: " + length + "\r\n");
break;
}
}
} catch(IOException e){
System.err.println("Usage: java WebServerMain <document_root> <port>");
}
}
public static void main(String args[]) {
try {
String cd = "/"+ args[0]; // This is the string that user chooses to pick the directory.
int port;
port = Integer.parseInt(args[1]);
int length = 0; // In order to find the length of the content.
String request;
String response;
final String dir = System.getProperty("user.dir");
System.out.println("current dir = " + dir+cd);
// Create a ServerSocket to listen on that port.
ServerSocket ss = new ServerSocket(port);
// Now enter an infinite loop, waiting for & handling connections.
for (;;) {
// Wait for a client to connect. The method will block;
// when it returns the socket will be connected to the client
Socket socket = ss.accept();
// Get input and outputstreams to talk to the client
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
String userInput = in.readLine();
System.out.println(userInput);
System.out.println("Final dir is " + dir+userInput.split(" ")[1]);
String str;
String content = "";
if(!userInput.split(" ")[0].equals("GET") && !userInput.split(" ")[0].equals("HEAD")){
out.println("HTTP/1.1 501 Not Implemented");
} // Checking, if the user chose correct options, GET or HEAD. If neither, we shall print 501 status code.
else {
try {
BufferedReader readContent = new BufferedReader(new FileReader(dir+cd+userInput.split(" ")[1]));
while ((str = readContent.readLine()) != null) {
content += str;
} // If the file exists, we are reading its content to the string called content. String str is a temporary string.
length = content.length();
out.println(userInput.split(" ")[2] + " 200 OK");
} catch (FileNotFoundException f) {
out.println(userInput.split(" ")[2] + " 404 Not Found");
out.close(); // Flush and close the output stream
in.close(); // Close the input stream
socket.close(); // Close the socket itself
}
if (userInput.split(" ")[0].equals("GET")) {
printToClient(length, in, out);
out.println(content);
} else if (userInput.split(" ")[0].equals("HEAD")) {
printToClient(length, in, out);
}
}
// Close socket, breaking the connection to the client, and
// closing the input and output streams
out.close(); // Flush and close the output stream
in.close(); // Close the input stream
socket.close(); // Close the socket itself
} // Now loop again, waiting for the next connection
}
// If anything goes wrong, print an error message
catch (IOException e) {
System.err.println(e.getMessage());
}
catch (ArrayIndexOutOfBoundsException a){
System.err.println("Usage: java WebServerMain <document_root> <port>");
}
}
}
【问题讨论】: