HTTP协议浅析(中):请求报文和响应报文

1. 请求报文格式

1.1 服务器测试代码

服务器测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
     // 创建通信端点:套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        perror("socket");
        return -1;
    }  

    // 设置本地地址结构体
    struct sockaddr_in my_addr;
    bzero(&my_addr, sizeof(my_addr));   // 清空
    my_addr.sin_family = AF_INET;       // ipv4
    my_addr.sin_port   = htons(8000);   // 端口
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip  

    // 绑定
    int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
    if( err_log != 0)
    {
        perror("binding");
        close(sockfd);
        return -1;
    }  

    err_log = listen(sockfd, 10); // 监听,监听套接字改为被动
    if(err_log != 0)
    {
        perror("listen");
        close(sockfd);
        return -1;
    }     

    printf("listen client @port=%d...\n", 8000); 

    int connfd;
    connfd = accept(sockfd, NULL, NULL);    // 等待连接  

    char buf[8*1024] = {0};
    read(connfd, buf, sizeof(buf));
    printf("%s", buf);

    while(1)
    {
        NULL;
    }

    return 0;
}

浏览器输入url地址:

终端启动服务器程序,测试http的请求报文:

1.2 请求报文格式说明

HTTP 请求报文由请求行、请求头部、空行、请求包体4个部分组成,如下图所示:

1)请求行

请求行由方法字段、URL 字段 和HTTP 协议版本字段 3 个部分组成,他们之间使用空格隔开。常用的 HTTP 请求方法有 GET、POST。

GET:

  • 当客户端要从服务器中读取某个资源时,使用GET 方法。GET 方法要求服务器将URL 定位的资源放在响应报文的数据部分,回送给客户端,即向服务器请求某个资源。
  • 使用GET方法时,请求参数和对应的值附加在 URL 后面,利用一个问号(“?”)代表URL 的结尾与请求参数的开始,传递参数长度受限制,因此GET方法不适合用于上传数据。
  • 通过GET方法来获取网页时,参数会显示在浏览器地址栏上,因此保密性很差。
GET / HTTP/1.1
Host: 192.168.11.80:9889
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

POST:

  • 当客户端给服务器提供信息较多时可以使用POST 方法,POST 方法向服务器提交数据,比如完成表单数据的提交,将数据提交给服务器处理。
  • GET 一般用于获取/查询资源信息,POST 会附带用户数据,一般用于更新资源信息。POST 方法将请求参数封装在HTTP 请求数据中,而且长度没有限制,因为POST携带的数据,在HTTP的请求正文中,以名称/值的形式出现,可以传输大量数据。
POST /search HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint,application/msword, application/x-silverlight, application/x-shockwave-flash, */*
Referer: <a href="http://www.google.cn/">http://www.google.cn/</a>
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)
Host: <a href="http://www.google.cn">www.google.cn</a>
Connection: Keep-Alive
Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g;
NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  

hl=zh-CN&source=hp&q=domety 

2)请求头部

请求头部为请求报文添加了一些附加信息,由“名/值”对组成,每行一对,名和值之间使用冒号分隔。

请求头部通知服务器有关于客户端请求的信息,典型的请求头有:

请求头 含义
User-Agent 请求的浏览器类型
Accept 客户端可识别的响应内容类型列表,星号“ * ”用于按范围将类型分组,用“ / ”指示可接受全部类型,用“ type/* ”指示可接受 type 类型的所有子类型
Accept-Language 客户端可接受的自然语言
Accept-Encoding 客户端可接受的编码压缩格式
Accept-Charset 可接受的应答的字符集
Host 请求的主机名,允许多个域名同处一个IP 地址,即虚拟主机
connection 连接方式(close或keepalive)
Cookie 存储于客户端扩展字段,向同一域名的服务端发送属于该域的cookie

3)空行

最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。

4)请求包体

请求包体不在GET方法中使用,而是POST方法中使用。

POST方法适用于需要客户填写表单的场合。与请求包体相关的最常使用的是包体类型Content-Type和包体长度Content-Length。

2. 响应报文格式

2.1 客户端测试代码

启动nginx服务器:

编写客户端程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
     // 创建通信端点:套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);  

    // 设置服务器地址结构体
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(server_addr)); // 初始化服务器地址
    server_addr.sin_family = AF_INET;   // IPv4
    server_addr.sin_port = htons(80); // nginx服务器监听的端口
    inet_pton(AF_INET, "192.168.31.109", &server_addr.sin_addr);   // 服务器ip  

     // 主动连接服务器
    int err_log = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if(err_log != 0)
    {
        perror("connect");
        close(sockfd);
        return -1;
    }

    //http请求报文包
    char send_buf[] =
        "GET /mike.html HTTP/1.1\r\n"
        "Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*\r\n"
        "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3\r\n"
        "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)\r\n"
        "Accept-Encoding: gzip, deflate\r\n"
        "Host: 192.168.31.109:8000\r\n"
        "Connection: Keep-Alive\r\n"
        "\r\n";

    //发送http请求报文包
    send(sockfd, send_buf, sizeof(send_buf)-1, 0);

    //获取http响应报文
    char recv_buf[8*1024] = {0};
    recv(sockfd, recv_buf, sizeof(recv_buf), 0);
    printf("%s", recv_buf);

    return 0;
}

在浏览器中输入url地址,得到test.html网页:

启动程序,测试http的成功响应报文:

在浏览器中输入url地址,没有得到相应网页:

启动程序,测试http的失败响应报文:

2.2 响应报文格式说明

HTTP 响应报文由状态行、响应头部、空行、响应包体4个部分组成,如下图所示:

1)状态行

状态行由 HTTP 协议版本字段、状态码和状态码的描述文本3个部分组成,他们之间使用空格隔开。

状态码:

状态码由三位数字组成,第一位数字表示响应的类型,常用的状态码有五大类如下所示:

状态码 含义
1xx 表示服务器已接收了客户端请求,客户端可继续发送请求
2xx 表示服务器已成功接收到请求并进行处理
3xx 表示服务器要求客户端重定向
4xx 表示客户端的请求有非法内容
5xx 表示服务器未能正常处理客户端的请求而出现意外错误

常见的状态码举例:

状态码 含义
200 OK 客户端请求成功
400 Bad Request 请求报文有语法错误
401 Unauthorized 未授权
403 Forbidden 服务器拒绝服务
404 Not Found 请求的资源不存在
500 Internal Server Error 服务器内部错误
503 Server Unavailable 服务器临时不能处理客户端请求(稍后可能可以)

2)响应头部

响应头可能包括:

响应头 含义
Location Location响应报头域用于重定向接受者到一个新的位置
Server Server 响应报头域包含了服务器用来处理请求的软件信息及其版本
Vary 指示不可缓存的请求头列表
Connection 连接方式

3)空行

最后一个响应头部之后是一个空行,发送回车符和换行符,通知服务器以下不再有响应头部。

4)响应包体

服务器返回给客户端的文本信息。

时间: 2024-08-08 09:37:09

HTTP协议浅析(中):请求报文和响应报文的相关文章

重温Http协议--请求报文和响应报文

http协议是位于应用层的协议,我们在日常浏览网页比如在导航网站请求百度首页的时候,会先通过http协议把请求做一个类似于编码的工作,发送给百度的服务器,然后在百度服务器响应请求时把相应的内容再通过http协议做一个类似于解码的工作,这样浏览器才能理解这个数据,然后为我们展示出来百度首页. 这相当于是一种规范,网络中数据的传输在位于应用之下的各层(传输层,应用层)来完成的,在tcp/ip协议接收到数据时,我们是不能直接使用和浏览的,需要先通过一种规范来进行梳理,也就是解码,得到浏览器支持的一种格

Http协议--请求报文和响应报文

       http协议是位于应用层的协议,我们在日常浏览网页比如在导航网站请求百度首页的时候,会先通过http协议把请求做一个类似于编码的工作,发送给百度的服务器,然后在百度服务器响应请求时把相应的内容再通过http协议做一个类似于解码的工作,这样浏览器才能理解这个数据,然后为我们展示出来百度首页. 这相当于是一种规范,网络中数据的传输在位于应用之下的各层(传输层,应用层)来完成的,在tcp/ip协议接收到数据时,我们是不能直接使用和浏览的,需要先通过一种规范来进行梳理,也就是解码,得到浏览

HTTP 请求报文和响应报文

HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. 1.请求报文一个HTTP请求报文由请求行(request line).请求头部(header).空行和请求数据4个部分组成,下图给出了请求报文的一般格式. (1)请求行 请求行由请求方法字段.URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔.例如,GET /index.html HTTP/1.1. HTTP协议的请求方法有GET.POST.HEAD.

HTTP请求报文和响应报文

HTTP报文分为请求报文(request message)与响应报文(response message). 一.报文的组成部分 一个HTTP报文由3部分组成,分别是: (1).起始行(start line) (2).首部(header) (3).主体(body) 示例: HTTP/1.0 200 OK //起始行 Content-type:text/plain //首部 Content-length:19 //首部 Hi I'm a message! 主体 1.1 请求报文与响应报文的格式 请求

HTTP请求报文与响应报文

一.HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. 一个HTTP请求报文由请求行(request line).请求头部(header).空行和请求数据4个部分组成,下图给出了请求报文的一般格式. 网上复制了一个图片(转载自华山大师兄): 给一个更加清晰,明了的图片: 以下逐步分析各个数据部分的作用. 1.请求行 请求行由请求方法字段.URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔. 例如打开路径

一个HTTP连接是包含两部分的,请求报文和响应报文这俩组合起来才是一次完整的HTTP请求,并不会单独显示请求报文或者响应报文

一个HTTP连接是包含两部分的,请求报文和响应报文这俩组合起来才是一次完整的HTTP请求,并不会单独显示请求报文或者响应报文. 2.注意看,一次HTTP请求,是包括这两部分的

浅析HTTP协议的请求报文和响应报文

1.HTTP协议与报文简介  HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器和万维网服务器之间互相通信的规则. 而客户端与服务端通信时传输的内容我们称之为报文.  HTTP就是一个通信规则,这个规则规定了客户端发送给服务器的报文格式,也规定了服务器发送给客户端的报文格式. 客户端发送给服务器的称为"请求报文",服务器发送给客户端的称为"响应报文". 2.报文格式    报文格式: 报文首部  空行  

IP封包协议头/TCP协议头/TCP3次握手/TCP4次挥手/UDP协议头/ICMP协议头/HTTP协议(请求报文和响应报文)/IP地址/子网掩码(划分子网)/路由概念/MAC封包格式

IP协议头IP包头格式: 1.版本号:4个bit,用来标识IP版本号.这个4位字段的值设置为二进制的0100表示IPv4,设置为0110表示IPv6.目前使用的IP协议版本号是4. 2.首部长度:4个bit.标识包括选项在内的IP头部字段的长度. 3.服务类型:8个bit.服务类型字段被划分成两个子字段:3bit的优先级字段和4bit TOS字段,最后一位置为0. 4bit的TOS分别代表:最小时延,最大吞吐量,最高可靠性和最小花费.4bit中只能将其中一个bit位置1.如果4个bit均为0,则

HTTP 请求报文和响应报文的格式

HTTP 请求报文 由请求行.请求头部.空行 和 请求包体 4 个部分组成: (1)请求行:请求行由方法字段.URL 字段 和HTTP 协议版本字段 3 个部分组成,他们之间使用空格隔开.常用的 HTTP 请求方法有 GET.POST.HEAD.PUT.DELETE.OPTIONS.TRACE.CONNECT; (2)请求头部:请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号":"分隔.请求头部通知服务器有关于客户端请求的信息: (3)空行:最后一个请求头之后是一个空行,发送