关于HTTP协议

HTTP协议

超文本传输协议,纯文本格式。
HTTP是基于TCP/IP协议来传递数据的。

HTTP协议工作于客户端-服务器端架构(C/S)上。浏览器作为HTTP客户端通过url向HTTP服务器端即WEB服务器发送请求

认识URL

Uniform Resourse Loctor 即统一资源定位符
URL就是我们平时所说的网址。
这里写图片描述
http协议默认端口号是80
https默认端口号是443
这里带层次的文件路径应该理解成一个相对路径,相对的是HTTP服务器的根目录,浏览器只能获取到这个根目录下的文件或数据,而不能访问其他目录下的资源。
https:相比http协议多了一层加密层ssl,功能是反运营商劫持。

当我们在在百度首页输入C++,再按下回车后,查询字符串变成了kd=c%2b%2b,这是因为特殊字符被进行了转码操作。

认识urlencode 和urldecode
像 % ? / :等一些特殊字符,已经被url当作特殊字符处理了,当输入的查询串中有这样的特殊字符,就先对这些特殊字符进行转义。
转义的规则如下:
将需要转码的字符转为16进制,然后从右到左,取4位(不⾜足4位直接处理),每2位做⼀一位,前⾯面加上%,编码成%XY格式
比如上面的C++,‘+’的ASCII码是43,对应的十六进制数就是2B,转码成c%2b%2b。

urldecode解码是urlencode的逆过程
url编码与解码工具

HTTP协议格式

1.HTTP请求格式
  • 首行:[方法]+url+版本号
  • header:请求的属性,冒号分割的键值对,每组属性之间以’\n’分割,遇到空行表示header结束
  • body:空行后的内容都是body,GET请求body一般为空字符串;若body存在,header部分会有一个Content-Length属性来标记body的长度

当我们访问百度首页时:
这里写图片描述
常见的header有:

  • Host:客户端告诉服务器请求url中的Web名称和端口号
  • Connection:用来告诉服务器是否可以维持固定的HTTP连接。HTTP/1.1使用Keep-Alive为默认值
  • User-Agent:用户操作系统和浏览器版本信息(可判定用户是手机还是PC端访问)
  • Referere:当前页面是从哪个页面跳转过来的
  • Location:搭配3XX状态码使用,当浏览器访问页面旧位置不存在时,重定向到该页面的新位置,告诉客户端接下来要去哪里访问
  • Cookie:用于在客户端存储少量信息,服务器返回给客户端的用户信息,也可以用来实现会话功能。
    通常保存身份信息,通过响应报文中的Set-Cookie字段,服务器返回的信息就会被浏览器保存下来,当浏览器再次访问同一个网站时就会自动在cookie中带上身份信息,多用于用户注册、登陆等。

字符串长度一般上限

  • Content-Type:实体的数据类型(text/html等)
  • Content-Length:body部分的长度

HTTP的方法也有多种

  • GET:通过请求url获得资源
    若请求的资源是文本则原样返回,若是与业务相关的CGI程序,则执行程序后返回结果
  • POST:传输实体主体,即向指定资源提交数据进行处理请求(例如提交表单或上传文件)
  • PUT:传输文件
  • DELETE:请求服务器删除指定页面
  • OPTIONS:查询服务器支持那些方法
  • HEAD:获得报文首部
  • TRACE:回显服务器收到的请求,用于测试诊断

最常用的就是GET和POST方法

GET方法一般不带body,POST方法一般都带body

2.HTTP响应格式
  • 首行:版本号 状态码 状态描述
  • Header:响应的属性。冒号分隔的键值对,每组属性之间用’\n’分割,出现空行表示header部分结束
  • Body:body中的内容就是HTTP服务器响应的结果,若返回了一个html页面,那么html页面内容就在body中

这里写图片描述

HTTP的状态码:
状态码是当客户端向服务器发送请求时,描述返回的请求结果。通过状态码,用户可以知道服务器端是正常处理了请求还是出现了错误。

这里写图片描述
状态码的数量多达60余种。
这里我们只介绍一些常见的状态码:

  • 200 OK 请求已正常处理
  • 204 No Content 请求已正常处理,但无资源可返回
  • 206 Partial Content 表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求
  • 301 Moved Permanently 永久性重定向
  • 302 Found 临时性重定向
  • 303 See Other 该状态码表示由于请求对应的资源存在着另一个 URI ,应使用 GET 方法定向获取请求的资源。和302功能相同,但必须使用GET方法获取资源。

    当 301 、 302 、 303 响应状态码返回时,几乎所有的浏览器都会把 POST 改成 GET ,并删除请求报文内
    的主体,之后请求会自动再次发送。

  • 400 Bad Request 表示请求报文中存在语法错误。

  • 401 Unauthorized 该状态码表示发送的请求需要有通过 HTTP 认证
  • 403 Forbidden 表示请求资源的访问被服务器拒绝了。(一般是访问权限的问题)
  • 404 Not Found 服务器上无法找到请求的资源
  • 500 Internal Server Error 服务器端在执行时法发生错误
  • 503 Service Unavailable 服务器处于超负载或停机维护,无法处理请求
  • 504 Bad Gateway 网关超时

GET /favicon.ico HTTP/1.1
这个HTTP请求首行中的favicon,ico一般是缩略的网站图标,它显示在浏览器的地址栏、浏览器标签上或者在收藏夹上,是展示网站个性的缩略logo标志,也可以说是网站头像,目前主要的浏览器都支持favicon.ico图标,如果要让网站看起来更专业、更美、更有个性,favicon.ico是必不可少的。

HTTP协议也存在一些缺点:

  • 通信使用明文(不加密),内容可能会被窃听
  • 不验证通信方身份,所以有可能遭遇伪装
  • 无法证明报文的完整性,报文在收到时有可能已经被篡改

在所有未加密的协议中,这些问题都会存在

使用 HTTPS 通信机制可以有效地防止这些问题。
HTTP 协议中没有加密机制,但可以通过和 SSL ( Secure Socket Layer ,安
全套接层)或 TLS ( Transport Layer Security ,安全层传输协议)的组合使用,加密 HTTP 的通信内容。
用 SSL 建立安全通信线路之后,就可以在这条线路上进行 HTTP 通信了。与 SSL 组合使用的 HTTP 被称为 HTTPS ( HTTP Secure ,超文本传输安全协议)。

实现一个超简洁版的HTTP服务器

响应结果是自己手动构造好的”hello world”页面

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;

//初始化服务器
int ServerInit(const char* ip,short port)
{
  int listen_sock=socket(AF_INET,SOCK_STREAM,0);
  if(listen_sock<0)
  {
    perror("socket");
    return -1;
  }

  sockaddr_in addr;
  addr.sin_family=AF_INET;
  addr.sin_addr.s_addr=inet_addr(ip);
  addr.sin_port=htons(port);
  int ret=bind(listen_sock,(sockaddr*)&addr,sizeof(addr));
  if(ret<0)
  {
    perror("bind");
    return -1;
  }
  ret=listen(listen_sock,5);
  if(ret<0)
  {
    perror("listen");
    return -1;
  }
  return listen_sock;
}


//线程入口函数
void* ThreadEntry(void *arg)
{
  int64_t new_sock=(int64_t)arg;//64位机器上指针大小为8个字节,若转成int存在数据丢失

  //1.读数据并解析,由于此处无脑返回helloworld,所以我们只读出数据不解析
  char buf[1024*10]={0};
  read(new_sock,buf,sizeof(buf)-1);
  //2.根据请求计算相应,此处不需要进行计算
  //3.把响应写回给客户端

  const char* first_line="HTTP/1.1 200 OK\n";//首行
  const char* blank_line="\n";//空行
  const char* body="<h1>hello world</h1>";//body
  char header[1024]={0};
  sprintf(header,"Content_Length:%lu\n",strlen(body));//header
  write(new_sock,first_line,strlen(first_line));
  write(new_sock,header,strlen(header));
  write(new_sock,blank_line,strlen(blank_line));
  write(new_sock,body,strlen(body));
  return NULL;

}


int main(int argc,char *argv[])
{
  if(argc!=3)
  {
    printf("Usage: ./http_server.c [ip] [port]\n");
    return 1;
  }

  //////////////////////////////////////////////////////////////
  //http服务器往往是基于TCP来实现的
  //1.创建一个TCP服务器
  //2.按照http协议的格式解析请求,并按照http协议的格式构造响应
  //////////////////////////////////////////////////////////////

  int listen_sock=ServerInit(argv[1],atoi(argv[2]));
  if(listen_sock<0)
  {
    printf("ServerInit failed!\n");
    return 1;
  }
  printf("ServerInit OK!\n");

  while(1)
  {
    sockaddr_in peer;
    socklen_t len=sizeof(peer);
    int64_t new_sock=accept(listen_sock,(sockaddr*)&peer,&len);
    if(new_sock<0)
    {
      perror("accept");
      continue;
    }
    pthread_t tid;
    pthread_create(&tid,NULL,ThreadEntry,(void*)new_sock);
    pthread_detach(tid);
  }
  close(listen_sock);

  return 0;
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值