0

我正在使用浏览器通过简单地输入地址 127.0.0.1:1501/filename.png 向服务器发送获取请求。目的是从服务器下载文件。服务器成功接收请求并加载所选文件,它还进入while循环并多次执行打印方法,这意味着正在发送某些东西,但在“网络”选项卡中的谷歌浏览器上检查我只得到filename.png失败我不明白为什么这段代码似乎不起作用。print 是一个简单地调用 System.out.println() 方法的方法

public class MainClassServer {
    public static void main(String[] args){
        // TODO Auto-generated method stub
        ServerSocket server = null;
        try {
            server = new ServerSocket();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try {
            server.bind(new InetSocketAddress("127.0.0.1", 1501));
        } catch (UnknownHostException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }


        while(true) {
            String message;
            Socket client = null;
            print("Waiting for client...");
            try{
                client = server.accept();
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
            BufferedReader reader = null;
            DataOutputStream writer = null;

            try {
                reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
                writer = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                message = reader.readLine();

                if(message!=null) {
                    //I get the correct filename with string manipulation
                    // I correctly access the file in fact it exist
                    File file = new File(path);

                    if(file.exists()) {
                        byte[] bytes = new byte[1024];
                        InputStream in = new FileInputStream(path);
                        int count;
                        while ((count = in.read(bytes)) > 0) {
                            //the program print some bytes so it writes something to someone
                            print("Sending " + count + " bytes");
                            writer.write(bytes, 0, count);
                        }
                        writer.flush();
                    }else {
                        print("File does not exsist.");
                    }


                    writer.close();
                    reader.close();
                    server.close();
                    break;  
                }

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }


}
4

2 回答 2

2

您根本没有遵循HTTP 1.x 协议,甚至没有关闭:

  • 您没有读取和解析浏览器的 HTTP 请求。您正在阅读请求的第一行,而忽略了请求的其余部分(可能并且通常超过 1 行)。而且您甚至没有解析第一行-其中的数据不仅仅是文件路径。它包含请求方法名称(即GET),后跟文件路径,然后是 HTTP 版本号。

  • 您没有发回格式正确的 HTTP 响应。您只是按原样发送原始文件字节,而不告诉客户端请求是否成功,或者描述您发送的文件数据类型。您必须发回包含 HTTP 版本号的 HTTP 状态行,然后是成功/失败错误代码,然后是人类可读的状态文本。然后发送描述文件类型、长度、传输格式等的 HTTP 头,最后发送文件的字节。

基本上,到目前为止,您实现的是一个HTTP 0.9服务器(它确实使用单行请求 - 您仍然没有正确解析它 - 并且除了文件的原始字节之外没有额外的响应细节)。这种服务器不适用于所有现代 Web 浏览器都使用的 HTTP 1.0+ 请求。HTTP 1.1 是目前大多数现代系统使用的分解标准(尽管许多系统开始向HTTP/2过渡)。

您确实应该使用适当的 HTTP 服务器,而不是普通的 TCP 服务器。HTTP 很复杂,从头开始实施并非易事。您应该改用预先存在的实现。例如,Java 有一个内置HttpServer类。

于 2019-11-07T19:15:10.467 回答
2

浏览器在请求时总是期望返回 HTTP 响应。如果您的客户端是简单的套接字客户端,那么您将在DataOutputStream为 HTTP 写入文件时获得该文件,至少您需要最小的 HTTP 响应格式。如果您在响应中添加这 2 个标头,您可能会得到预期的行为。

if(file.exists()) {
    byte[] bytes = new byte[1024];
    InputStream in = new FileInputStream(path);
    int count;
    // Setting HTTP response headers
    writer.writeBytes("HTTP/1.0 200 OK\r\n");
    writer.writeBytes("Content-Type: image/jpeg\r\n");
    writer.writeBytes("\r\n");
    while ((count = in.read(bytes)) > 0) {
        //the program print some bytes so it writes something to someone
        print("Sending " + count + " bytes");
        writer.write(bytes, 0, count);
    }
    writer.flush();
}else {
    print("File does not exsist.");
}
于 2019-11-07T19:42:14.507 回答