java - 多线程 http 服务器从客户端浏览器获取 GET 和 POST

标签 java networking network-programming network-protocols

我正在尝试运行一个简单的多线程服务器,该服务器获取 URL 并允许浏览器将文件上传到服务器( GET 和 POST ),它使用 GET 获取网页我在 POST 方面遇到问题,这是我的 WebServer我正在使用它来进行上传工作。注意:HttpRequest是另一个处理线程的类

import java.net.*;
import java.io.*;


public class WebServer
{

    public WebServer(int port)
    {

        System.out.println("starting web server on port " + port);

        ServerSocket serverSocket = null;

        try
        {
            //create the server
            serverSocket = new ServerSocket(port);
        }catch(IOException ex)
        {
            System.out.println("could not open port " + port);
            System.exit(1);
        }

        //loop indefinitely
        while(true)
        {
            try
            {
                Socket connection = null;
                connection = serverSocket.accept();
                //accept the connection

                //create a new thread, start it and return to the waiting state
                HttpRequest request = new HttpRequest(connection);
                Thread t = new Thread(request);
                t.start();

            }catch(IOException ex)
            {
                //fail if an error occurs
                System.out.println("problem accepting connection");
                System.exit(1);
            }
        }

    }

    public static void main(String[] args)
    {

        //simple validation for the port number
        if(args.length != 1)
        {
            System.out.println("please specify a port");
            System.exit(1);
        }

        int port = -1;
        try
        {
            port = Integer.parseInt(args[0]);

        }catch(NumberFormatException ex)
        {
            System.out.println("invalid port number");
            System.exit(1);
        }

        WebServer server = new WebServer (port);

    }

}

这里是 Http 实现可运行的

import java.net.*;
import java.io.*;

public class HttpRequest implements Runnable
{

    private DataInputStream input = null;
    private Socket connection;

    private static DataOutputStream output = null;

    public HttpRequest(Socket connection)
    {
        this.connection = connection;
    }

    //required method so this can be used as a thread
    public void run()
    {
        try
        {
            //try and get the streams
            input = new DataInputStream(connection.getInputStream());
            output = new DataOutputStream(connection.getOutputStream());
        }
        catch(IOException ex)
        {
            System.out.println("could not get input/output streams from connection: " + connection.toString());
            return;
        }

        try
        {
            StringBuilder response = new StringBuilder("");

            String request = input.readLine();

            System.out.println("request: " + request);

            String[] requestArray = request.split(" ");

            //read off and ignore the rest of the input
            //added so this can be tested with real browsers
            while(input.available() != 0)
            {
                input.read();
            }

            if (requestArray.length != 3)
            {
                //request should be of the format GET /index.html HTTP/1.1, die if a bad request comes in
                System.out.println("bad request: " + request);
                return;
            }else
            {
                //requested file should be the second entry, remove the leading '/'
                File requestedFile = new File(requestArray[1].substring(1));

                System.out.println("requested file: " + requestedFile);

                //check the requested file exists
                if(requestedFile.exists())
                {
                    System.out.println("file found, sending response");

                    DataInputStream fileInput = new DataInputStream(new FileInputStream(requestedFile));

                    //output HTTP header, must be followed by two new lines
                    response.append("HTTP/1.1 200 OK\n\n");

                    String line = fileInput.readLine();

                    while(line != null)
                    {
                        response.append(line);
                        line = fileInput.readLine();
                    }

                    fileInput.close();

                    output.writeBytes(response.toString());
                    output.flush();
                    output.close();

                    Logger.writeToLog("Request: " + request + "\r\nResponse: " + response.toString());

                }
                else
                {
                    System.out.println("file not found, sending 404");

                    response.append("HTTP/1.1 404 Not Found\n\n");
                    output.writeBytes(response.toString());

                    output.flush();
                    output.close();
                }

            }

        }
        catch(IOException ex)
        {
            System.out.println("cannot read request from: " + connection.toString() + ex.toString());
            return;
        }
        catch(NullPointerException ex)
        {
            System.out.println("bad request: " + connection.toString());
            return;
        }

        try
        {
            input.close();
            output.close();

            connection.close();
        }
        catch(IOException ex)
        {
            System.out.println("Can't close connection: " + connection.toString());
            return;
        }
    }

}

最佳答案

您的问题是您的 HttpRequest 类没有正确实现 HTTP 协议(protocol)。对于初学者,您假设所有请求都是 GET 请求,并且忽略请求行后面的 header 行。

您需要做的是……彻底阅读 HTTP 1.1 规范……并重写您的代码,以便它读取和处理请求,并根据规范规定的方式生成响应。

或者,不要浪费时间重新发明轮子(可能是错误的)。使用现有的 Web 容器框架,或现有的 HTTP 协议(protocol)栈,例如 Apache HttpComponents。

关于java - 多线程 http 服务器从客户端浏览器获取 GET 和 POST,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9730898/

相关文章:

java - 如何在 Javadoc 中查找所有返回类型的方法?

java - 使用超线程缓冲读取文件

互联网上的 Java 套接字 : ConnectException (operation timed out)

networking - 如果 TCP 是面向连接的,为什么数据包会遵循不同的路径?

linux - 哪种双栈服务器方法更好?

java - Keycloak SAML 重定向在登录后卡在循环中

java - getClass() 返回 null 但 Foo.class 工作

networking - 为什么我收到错误 ("status":405 ,"error" :"Method Not Allowed") upon sending data to Thingsboard device via command line

Python socket.connect 有时会挂起

c++ - gethostbyaddr() 函数是否使用互联网将 IP 地址转换为主机名?