自己来做一个简单的web服务器(一)理解基本的http协议

来源:互联网 发布:联合办公 知乎 编辑:程序博客网 时间:2024/05/17 06:37

简介

本部分我们将简单学习一下http协议,才能为后面的web服务器的开发打好基础。

一个Http协议,涉及到请求Request和应答Response,这里就从这两者入手对协议进行一个简单的讲解。

后面将以一个实际的java程序来实现一个简单的web服务器。

 

请求

      官方协议文档地址为https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html

请求是从客户端,一般是浏览器,发送给服务器,

      下面是一次请求的简单结构:

            Request       = Request-Line          

                        *(( general-header       

                         | request-header        

                         | entity-header )CRLF) 

                        CRLF

                        [ message-body ]         

      一次Request,由Request-Line,一些头信息,以及消息体message-body来组成。

      Request-Line在消息的第一行里,包括请求的Method方法(作用到资源上),资源标识符Request-URI以及使用的协议版本号HTTP-Version,后面跟着回车换行符CRLF。具体格式如下所示:

      Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

      这里的SP就是空格分割符。

 

Method

      这个Method代表的是要作用在用Request-URI标记的资源上面的操作,是大小写敏感的。常见的Method包括:"OPTIONS","GET","HEAD","POST","PUT","DELETE","TRACE","CONNECT"和extension-method。

      某一个资源,在其上面能够允许进行的操作是不一样的。服务器端针对该http请求的回应里面,有一个代码,可以表示是否允许该操作作用于该资源上面。比如操作代码405(Method Not Allowed),就是表示该method不允许操作Request-URI标记的资源。而501(Not Implemented)则表示该method的操作在服务端没有实现。

对于web服务器而言,必须支持GET和HEAD命令,其他命令支持是可选的。在Allowheader字段,会列出来这个资源允许支持的命令列表。

 

Request-URI

Request-URI代表的是统一资源定位符,标记Method要进行操作的资源。

       Request-URI    = "*" | absoluteURI | abs_path |authority

Request-URI支持4种URI标记方法,根据request的不同,使用这4种URI标记方法。

        

      星号表示该请求并不适用于特定的资源,而是适用于服务器本身。这个只适合于那些不特定针对某个资源的方法。

当请求被用于一个代理时,使用absoluteURI。代理将把请求进行转发,然后返回一个响应。

Authority这里只是被CONNECT方法所使用。

我们日常最常见的,用来标识在服务器上的resource,就是传递abs_path,是URI的绝对路径:对于http请求而言,Request-URI给出这个URI的绝对路径,而Host代表的是服务器的主机,必须在Hostheader字段进行标记。Request-URI不能为空。例如:

      GET/pub/WWW/TheProject.html HTTP/1.1

       Host: www.w3.org

      如果初始的URI为空的话,必须设置为"/",这个代表的是服务器的根。

另外,Request-URI可能被进行16进制编码,而如果Request-URI被16进制编码的话,server侧必须进行解码才能正确的解析请求。对于无效的Request-URI,server必须以合适的状态码给予回应。

      对于一次internet请求标记的资源,由Request-URI和Hostheader字段来标记。而服务器简单遵循下列规则进行处理:

      1.   如果Request-URI是一个绝对的URL,里面已经包含了主机的信息,那么请求中任何主机头Hostheader字段值都必须被忽略。

      2.   如果Request-URI不是一个绝对URL,请求包括一个Hostheader主机请求头,要访问的主机由hostheader主机请求头的字段值决定。

      3.   如果按照规则1和规则2确定下来的主机是一个无效的主机的话,服务器必须返回400(Bad Request) 无效请求。

 

RequestHeader字段

      请求头字段允许客户传递一些关于请求的额外信息,这些信息用来描述请求request,以及关于client。充当请求修饰符的作用。

 

服务器的响应Response

      关于Response的规范协议,参考的协议地址为:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html

      在收到和解析一个请求消息后,服务器端用一个response消息来进行回应。

服务器端的response,其格式定义如下:

       Response      = Status-Line               
                 *(( general-header        
                | response-header        
                | entity-header ) CRLF)  
                CRLF
                [ message-body ]          

 

Status-Line状态行

           Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

      Status-Line是状态行,包含的字段包括:HTTP-Version, Status-Code和Reason-Phrase。这些字段之间通过空格来进行分隔。

      状态代码字段,即Status-Code,由3位数字组成,而原因字段Reason-Phrase以人们更加容易理解的方式来描述状态代码值Status-Code。

      要注意的是,状态代码字段的第1个数字,代表的是响应的类别。

      常见的状态码包括如下:

      - 1xx: 通告类 – 表示收到请求,将继续处理
      - 2xx: 成功 – 表示收到请求,理解并接受该命令
      - 3xx: 重定向- 要完成该请求,必须进一步的处理
      - 4xx: 客户端发生错误- 请求语法错误或者无法完成。
      - 5xx: 服务器端错误- 服务器端出错,无法完成一个有效的请求。

      下面是具体的状态代码

Status-Code    =

            "100"  ; Continue

          | "101"  ; Switching Protocols

          | "200"  ; OK

          | "201"  ; Created

          | "202"  ; Accepted

          | "203"  ; Non-Authoritative Information

          | "204"  ; No Content

          | "205"  ; Reset Content

          | "206"  ; Partial Content

          | "300"  ; Multiple Choices

          | "301"  ; Moved Permanently

          | "302"  ; Found

          | "303"  ; See Other

          | "304"  ; Not Modified

          | "305"  ; Use Proxy

          | "307"  ; Temporary Redirect

         | "400"  ; Bad Request

          | "401"  ; Unauthorized

          | "402"  ; Payment Required

          | "403"  ; Forbidden

          | "404"  ; Not Found

          | "405"  ; Method Not Allowed

          | "406"  ; Not Acceptable

          | "407"  ; Proxy Authentication Required

          | "408"  ; Request Time-out

          | "409"  ; Conflict

          | "410"  ; Gone

          | "411"  ; Length Required

          | "412"  ; Precondition Failed

          | "413"  ; Request Entity Too Large

          | "414"  ; Request-URI Too Large

          | "415"  ; Unsupported Media Type

          | "416"  ; Requested range not satisfiable

          | "417"  ; Expectation Failed

          | "500"  ; Internal Server Error

          | "501"  ; Not Implemented

          | "502"  ; Bad Gateway

          | "503"  ; Service Unavailable

          | "504"  ; Gateway Time-out

          | "505"  ; HTTP Version not supported

          | extension-code

      extension-code = 3DIGIT

      Reason-Phrase  = *<TEXT, excluding CR, LF>

 

Response Header 响应头字段

Response-header字段允许服务器传递关于response的额外信息,这些信息又不能放在Status-Line里。这些头字段提供一些server以及Request-URI要访问的信息。

       response-header = Accept-Ranges           
               | Age                     
               | ETag                    
               | Location                
               | Proxy-Authenticate      
               | Retry-After             
               | Server                  
               | Vary                    

                                                            | WWW-Authenticate       


原创粉丝点击