HTTP协议

更多linux和网络知识点:linux目录索引


目录:

一、什么是HTTP

  HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

  HTTP是一个属于应用层的面向对象的协议,基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

  HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。

二、HTTP之URL

  HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息

  URL,全称是UniformResourceLocator, 中文叫统一资源定位符,是互联网上用来标识某一处资源的地址。其实也就是我们平时上网所看到的网址

先来看一个标准的URL格式:

这里写图片描述

再来从网页上找出一个网址来分析URL内容:

https://www.so.com/s?q=C%2B%2B&src=srp&fr=none&psid=a9aeee8bb3fd74a7c3497e1c34903b84

  1. 协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在”HTTP”后面的“//”为分隔符

  2. 域名部分:该URL的域名部分为“www.so.com/s”。一个URL中,也可以使用IP地址作为域名使用,例如”192.168.0.178“

  3. 端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口;
    https的默认端口号是443,http的默认端口号是80

  4. 目录部分:域名后面跟的“/s”,这里表示的是你所查找资源的根目录,其中s是一个可执行程序,去服务器上查找关键字,在进行检索任务

  5. 参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“q=C%2B%2B&src=srp&fr=none&psid=a9aeee8bb3fd74a7c3497e1c34903b84”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。
四、HTTP之urlencode和urldecode

urlencode

上面的网址是自己搜索的关键词是C++,但是里面没有出现,而出现了”c=%2B%2B“等,这些字符都被当做特殊意义处理过了,这些被转义字符的转移规则为:将需要转码的字符转为16进制,然后从右向左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%xy的格式

urldecode

decode就是encode的逆过程,将编码格式为%xy转义成正常的字符

五、HTTP之请求消息Request

  
当客户端向服务器端发送一个请求应该包含以下信息:

这里写图片描述
  
一个例子:

这里写图片描述

通过抓包工具fiddler抓取到http的请求报文,可以看到以下信息:

  1. 请求行:请求方法为GET;URL(请求的资源)是http://192.168.0.198:8080/ ;版本号是HTTP/1.1

  2. 请求报头: 第二行至第七行,分别为:

  1. HOST:目标服务器,这里显示的是ip和端口号
  2. Connection:常连接(底层使用TCP协议,表示进行一次TCP连接,发送完数据不会关闭连接)
  3. User-Agent:浏览器的版本
  4. Accept:表示请求的资源,也是客户端可以接受的资源
  5. Accept-Encoding:接受的编码格式
  6. Accept-Language:接受的语言
六、HTTP之响应Response

当服务器向客户端响应时,响应报文应该包含以下格式

这里写图片描述

下面通过抓包工具来查看响应报文:

这里写图片描述

  1. 状态行:http的版本,状态码200 状态描述为OK
  2. 响应报头:这里只显示了资源的大小
  3. 空行:注意到长度下面是一个空行,不是响应的正文
  4. 响应的正文:这里是一个网页显示的一个字符串,hello world
七、HTTP的状态码

状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:

1xx:指示信息–表示请求已接收,继续处理
2xx:成功–表示请求已被成功接收、理解、接受
3xx:重定向–要完成请求必须进行更进一步的操作
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求

常见状态码:

200 OK                        //客户端请求成功
400 Bad Request               //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized              //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 
403 Forbidden                 //服务器收到请求,但是拒绝提供服务
404 Not Found                 //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error     //服务器发生不可预期的错误
503 Server Unavailable        //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

更多状态码:https://blog.csdn.net/zhangye3017/article/details/78429605

八、HTTP的方法
方法说明支持的HTTP协议的版本
GET获取资源1.0 1.1
POST传输实体主体1.0 1.1
PUT传输文件1.0 1.1
HEAD获取报文首部1.0 1.1
DELETE删除文件1.0 1.1
OPTIONS询问支持的方法1.1
CONNECT要求用隧道协议连接代理1.1

在这里重点说一下GET和POST的区别:

GET请求

GET /books/?sex=man&name=Professional HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意最后一行是空行

POST请求

POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive

name=Professional%20Ajax&publisher=Wiley
  1. GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.

  2. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.

  3. GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。

  4. GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

九、实现一个简单的HTTP服务器
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

// ./server  ip地址  端口号
int main(int argc,char* argv[])
{
    //进程 ip地址  端口号
    if(argc != 3){
        perror("Usage ./server [ip] [port]\n");
        return 1;
    }
    //ipv4 面向字节流  创建socket
    int new_sock = socket(AF_INET, SOCK_STREAM,0);
    if(new_sock < 0){
        perror("socket");
        return 2;
    }

    struct sockaddr_in server;//绑定的是服务器的ip和端口号
    server.sin_family = AF_INET;//协议族
    server.sin_addr.s_addr = inet_addr(argv[1]);//将ip专程4字节ip地址,在转成大端字节序
    server.sin_port = htons(atoi(argv[2]));


    //绑定端口号
    int ret = bind(new_sock, (struct sockaddr*)&server,sizeof(server));
    if(ret < 0){//绑定失败
        perror("bind");
        return 3;
    }

    //设置成监听状态,socket文件描述符,第二个参数为连接客户端的最大个数
    int lis = listen(new_sock, 5);
    if(lis < 0){
        perror("listen");
        return 4;
    }

    printf("listen success...\n");

    struct sockaddr_in client;
    while(1){
        //获取与客户端的连接,这里的结构体获取的是客户端的ip和端口号,还没传过来


        socklen_t len = sizeof(client);
        int client_sock = accept(new_sock,(struct sockaddr*)&client, &len);
        if(client_sock < 0){//获取失败,接着获取
            perror("accept");
            continue;
        }

        printf("Get connet[%s]:[%d]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
        char buf[1024*10];
        read(client_sock,buf,sizeof(buf)-1);
        printf("%s\n", buf);

        char msg[1024*10] = {0};
        const char* hello = "hello world";
        sprintf(msg, "HTTP/1.1 200 OK\nContent-Length:%lu\n\n%s",strlen(hello),hello);

        //将数据写回客户端
        ssize_t w = write(client_sock, msg, strlen(msg));

    }

    close(new_sock);
    return 0;
}

效果:

这里写图片描述

这里写图片描述

抓包 得到的结果:

这里写图片描述

注:以上摘自https://www.cnblogs.com/ranyonsue/p/5984001.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值