Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HTTP服务器-为favicon.ico提供服务_Java_Http_Web_Server - Fatal编程技术网

Java HTTP服务器-为favicon.ico提供服务

Java HTTP服务器-为favicon.ico提供服务,java,http,web,server,Java,Http,Web,Server,我正在尝试设置自己的JavaHTTP服务器,以便更好地理解http服务器以及在web的保护下发生的事情。我已经开发了一个非常简单的服务器,能够同时提供html页面和JSON格式的数据。然后我看到浏览器(我正在使用chrome,但假设其他浏览器也是一样)正在发送一个favicon.ico请求。我能够在我的服务器上识别该请求,因此我尝试提供一个随机下载的图标,并将其大小调整为16x16像素的png格式,因为这是互联网所要求的大小。这是我的代码,请注意,它不应该是任何专业的东西,而只是一些能满足我基本

我正在尝试设置自己的JavaHTTP服务器,以便更好地理解http服务器以及在web的保护下发生的事情。我已经开发了一个非常简单的服务器,能够同时提供html页面和JSON格式的数据。然后我看到浏览器(我正在使用chrome,但假设其他浏览器也是一样)正在发送一个favicon.ico请求。我能够在我的服务器上识别该请求,因此我尝试提供一个随机下载的图标,并将其大小调整为16x16像素的png格式,因为这是互联网所要求的大小。这是我的代码,请注意,它不应该是任何专业的东西,而只是一些能满足我基本教育目的的东西:

[set up ServerSocket and listen]
public static String err_header = "HTTP/1.1 500 ERR\nAccess-Control-Allow-Origin: *";
public static String success_header = "HTTP/1.1 200 OK\nAccess-Control-Allow-Origin: *";
public static String end_header = "\r\n\r\n";
while(true){
        try{
            System.out.println("Listening for new connections");
            clientSocket = server.accept();
            System.out.println("Connection established");
            InputStreamReader isr = new InputStreamReader(clientSocket.getInputStream());
            BufferedReader reader = new BufferedReader(isr);
            String getLine = reader.readLine();//first line of HTTP request
            handleRequest(getLine,clientSocket);
        }//end of try
        catch(Exception e){
            [error stuff]
        }//end of catch
    }//end of while
HandlerRequest方法:

public static void handleRequest(String getLine,Socket clientSocket) throws Exception{
    if(getLine.substring(5,16).equals("favicon.ico")){
        List<String> iconTag = new ArrayList<String>();
        iconTag.add("\nContent-Type: image/png");
        handleFileRequest("[file]",iconTag,clientSocket);
    }//end of if
    else{
        handleFileRequest("[file]",clientSocket);
    }//end of else
}//end of handleRequest
publicstaticvoidhandlerequest(stringgetline,socketclientsocket)抛出异常{
if(getLine.substring(5,16).equals(“favicon.ico”)){
List iconTag=new ArrayList();
iconTag.add(“\n内容类型:image/png”);
handleFileRequest(“[file]”,iconTag,clientSocket);
}//if结束
否则{
handleFileRequest(“[file]”,clientSocket);
}//别有用心
}//HandlerRequest结束
HandleFile请求图像:

public static void handleFileRequest(String fileName,List<String> headerTags,Socket clientSocket) throws Exception{
    OutputStream out = clientSocket.getOutputStream();
    BufferedReader read = new BufferedReader(new FileReader(fileName));
    out.write(success_header.getBytes("UTF-8"));
    Iterator<String> itr = headerTags.iterator();
    while(itr.hasNext()){
        out.write(itr.next().getBytes("UTF-8"));
    }//end of while
    out.write(end_header.getBytes("UTF-8"));
    String readLine = "";
    while((readLine = read.readLine())!=null){
        out.write(readLine.getBytes("UTF-8"));
    }//end of while
    out.flush();
    out.close();
}//end of handleFileRequest
publicstaticvoidhandlefilerequest(字符串文件名、列表头标签、套接字clientSocket)引发异常{
OutputStream out=clientSocket.getOutputStream();
BufferedReader read=新的BufferedReader(新文件读取器(文件名));
out.write(success_header.getBytes(“UTF-8”);
迭代器itr=headerTags.Iterator();
while(itr.hasNext()){
out.write(itr.next().getBytes(“UTF-8”);
}//结束
out.write(end_header.getBytes(“UTF-8”);
字符串readLine=“”;
而((readLine=read.readLine())!=null){
out.write(readLine.getBytes(“UTF-8”);
}//结束
out.flush();
out.close();
}//handleFileRequest结束
它似乎可以工作,当服务器发送文件时,浏览器显示200 OK响应,但没有favicon,当我将网络请求过滤为仅图像时,有一个图像是由正在服务的页面请求的,但favicon请求没有列在那里(favicon请求在“其他”部分)。类似地,当单击另一个图像时,图像会显示在预览中,而favicon请求的情况并非如此。截图:

同时,这是另一幅图像的外观,它在页面中显示得很好:

我也尝试过包含内容长度标题,但这似乎没有什么不同。我错过了什么明显的东西吗

另外,我只想澄清一下,我知道我可以在实际的html页面中包含favicon,目标不是这样做,而是理解它是如何工作的。

读取二进制文件 看来这封信的内容没有正确送达

我怀疑这很可能是因为您阅读其内容的方式:

逐行读取二进制内容是不合适的, 因为线的概念,还有UTF-8编码, 在二进制文件的上下文中没有意义。 这样你就不能一行一行地正确阅读二进制内容, 因为
BufferedReader
readLine
方法不会返回整行,因为它会从末尾剥离换行符。 您无法手动添加换行符,因为您无法确切知道它是什么

以下是读取二进制文件内容的一种更简单、正确的方法:

byte[] bytes = Files.readAllBytes(Paths.get("/path/to/file"));
一旦有了这些,就可以使用
bytes.length
的值轻松生成具有内容长度的正确文件头

在浏览器中访问页面时会发生什么情况 如果我们澄清一些事情,似乎对你有好处

在浏览器中打开URL时, 浏览器向web服务器发送GET请求,以下载您指定的原始URL的内容

一旦获得页面内容,它将发送进一步的GET请求:

  • 如果还没有,就去拿一个。此文件的位置可以在HTML文档中指定,否则浏览器将在默认情况下尝试获取
    SERVERNAME/favicon.ico
  • 获取文档中任何(有效)
    标记的
    src
    属性中指定的图像
  • 获取文档中任何(有效)
    标记的
    href
    属性中指定的样式表
  • 。。。类似地,对于
    标记,等等
favicon完全是装饰性的,以浏览器选项卡标题显示, 其他资源对于呈现页面至关重要。 它们在基于文本的浏览器(如lynx)中不是必不可少的, 这样的浏览器显然无法获取这些资源

这就是为什么需要favicon,以及如何申请favicon的原因

web服务器如何提供文件服务? 在最基本的情况下,为文件提供服务有两个重要的组成部分:

  • 生成适当的HTTP头:头中的每一行都采用
    name:value
    格式,每一行必须以
    \n
    结尾。 必须至少有一个
    内容类型
    标题。 标题必须以空行结尾

  • 终止标头的空白行之后, 内容可以是任何内容,甚至是二进制。 举例说明,, 考虑<代码> CURL< /COD>命令,它将URL的内容转储到标准输出。 如果运行

    将url卷曲到某个html文件
    , 您将看到html文件的内容。 如果运行指向某个图像文件的
    curl url
    , 您将看到图像文件的内容。 它将无法读取,并且您的终端可能会发出奇怪的声音。 您可以将输出重定向到具有
    curl url to some image file>image.png
    的文件, 这会给你一个图像文件, 二进制内容, 可以在任何图像查看器工具中打开

  • 简言之,提供文件实际上只是在标准输出上打印一个标题, 然后打印一个空行以终止标题, 这个
    byte[] bytes = Files.readAllBytes(Paths.get("/path/to/file"));
    
    curl -o file url-to-favicon
    cmp file /path/to/original
    
    HttpServer server = HttpServer.create(new InetSocketAddress(1234), 0);
    
    server.createContext("/favicon.ico", t -> {
      byte[] bytes = Files.readAllBytes(Paths.get("/path/to/favicon"));
      t.sendResponseHeaders(200, bytes.length);
      try (OutputStream os = t.getResponseBody()) {
        os.write(bytes);
      }
    });
    
    server.createContext("/", t -> {
      Charset charset = StandardCharsets.UTF_8;
      List<String> lines = Files.readAllLines(Paths.get("/path/to/index"), charset);
    
      t.sendResponseHeaders(200, 0);
    
      try (OutputStream os = t.getResponseBody()) {
        for (String line : lines) {
          os.write((line + "\n").getBytes(charset));
        }
      }
    });
    
    server.start();