HTTP的概念、原理、⼯作机制以及数据格式讲解(通俗易懂)

313 阅读5分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

HTTP的定义

⼀种⽹络传输协议,位于TCP / IP协议族的最顶层——应⽤层(这句话后⾯的课会详细解释)。

HTTP

Hypertext Transfer Protocol,超⽂本传输协议,和HTML (Hypertext Markup Language超⽂本标记语⾔)⼀起诞⽣,⽤于在⽹络上请求和传输HTML内容。超⽂本,即「扩展型⽂本」,指的是HTML中可以有链向别的⽂本的链接(hyperlink)。

image.png

HTTP的⼯作方式

浏览器:

⽤户输⼊地址后回⻋或点击链接->浏览器拼装HTTP报⽂并发送请求给服务器->服务器处理请求后发送响应报⽂给浏览器->浏览器解析响应报⽂并使⽤渲染引擎显示到界⾯

手机App:

⽤户点击或界⾯⾃动触发联⽹需求-> Android代码调⽤拼装HTTP报⽂并发送请求到服务器->服务器处理请求后发送响应报⽂给⼿机-> Android代码处理响应报⽂并作出相应处理(如储存数据、加⼯数据、显示数据到界⾯)

URL和HTTP报文

URL格式

三部分:协议类型、服务器地址(和端⼝号)、路径(Path)协议类型://服务器地址[:端⼝号]路径hencoder.com/users?gende…

报文格式

请求报文

image.png

响应报文

image.png

Request Method请求⽅法

GET

  • ⽤于获取资源
  • 对服务器数据不进⾏修改
  • 不发送Body
GET/users/1HTTP/1.1 
Host: api.github.com

对应Retrofit的代码:

@GET("/users/{id}")
Call<User>getUser(@Path("id") Stringid, @Query("gender") Stringgender);

POST

  • ⽤于增加或修改资源
  • 发送给服务器的内容写在Body里面
POST/usersHTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

name=rengwuxian&gender=male

对应Retrofit的代码:

@FormUrlEncoded
@POST("/users")
Call<User>addUser(@Field("name") Stringname, @Field("gender") Stringgender);

PUT

  • ⽤于修改资源
  • 发送给服务器的内容写在Body里面
PUT/users/1HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13gender=female

对应Retrofit的代码:

@FormUrlEncoded
@PUT("/users/{id}")
Call<User>updateGender(@Path("id") Stringid, @Field("gender") Stringgender);

DELETE

  • ⽤于删除资源
  • 不发送Body
DELETE/users/1HTTP/1.1
Host: api.github.com
@DELETE("/users/{id}"
Call<User>getUser(@Path("id") Stringid, @Query("gender") Stringgender);

HEAD

  • 和GET使⽤⽅法完全相同
  • 和GET唯⼀区别在于,返回的响应中没有Body

Status Code状态码

三位数字,⽤于对响应结果做出类型化描述(如「获取成功」「内容未找到」)。

  • 1xx:临时性消息。如:100(继续发送)、101(正在切换协议)
  • 2xx:成功。最典型的是200(OK)、201(创建成功)。
  • 3xx:重定向。如301(永久移动)、302(暂时移动)、304(内容未改变)。
  • 4xx:客户端错误。如400(客户端请求错误)、401(认证失败)、403(被禁⽌)、404(找不到内容)。
  • 5xx:服务器错误。如500(服务器内部错误)。

Header⾸部

作⽤:HTTP消息的metadata。

Host

⽬标主机。注意:不是在⽹络上⽤于寻址的,⽽是在⽬标服务器上⽤于定位⼦服务器的。

Content-Type

指定Body的类型。主要有四类:

1. text/html

请求Web⻚⾯是返回响应的类型,Body中返回html⽂本。格式如下:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 853

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
......

2. x-www-form-urlencoded

Web⻚⾯纯⽂本表单的提交⽅式。

image.png

格式如下:

POST/usersHTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

name=rengwuxian&gender=male

对应Retrofit的代码:

@FormUrlEncoded
@POST("/users")
Call<User>addUser(@Field("name") Stringname, @Field("gender") Stringgender);

3. multitype/form-data

Web⻚⾯含有⼆进制⽂件时的提交⽅式。格式如下:

image.png

POST/usersHTTP/1.1
Host: hencoder.com
Content-Type: multipart/form-data; boundary=----
WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Length: 2382

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="name"

rengwuxian
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="avatar"; filename="avatar.jpg"
Content-Type: image/jpeg

JFIFHHvOwX9jximQrWa......
------WebKitFormBoundary7MA4YWxkTrZu0gW--

对应Retrofit的代码:

@Multipart
@POST("/users")
Call<User>addUser(@Part("name") RequestBodyname, @Part("avatar")RequestBodyavatar);

...

RequestBodynamePart=RequestBody.create(MediaType.parse("text/plain"),nameStr);
RequestBodyavatarPart=RequestBody.create(MediaType.parse("image/jpeg"),avatarFile);
api.addUser(namePart, avatarPart);

4. application/json , image/jpeg , application/zip ...

单项内容(⽂本或⾮⽂本都可以),⽤于Web Api的响应或者POST / PUT的请求

请求中提交JSON

POST /users HTTP/1.1
Host: hencoder.com
Content-Type: application/json; charset=utf-8
Content-Length: 38

{"name":"rengwuxian","gender":"male"}

对应Retrofit的代码:

@POST("/users")
Call<User>addUser(@Body("user") Useruser);
...

//需要使⽤JSON相关的Converter
api.addUser(user);

响应中返回JSON

HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
content-length:234

[{"login":"mojombo","id":1,"node_id":"MDQ6VXNlcjE=","avatar_url":"https://avatars0.githubusercontent.com/u/1?v=4","gravat......

请求中提交⼆进制内容

POST /user/1/avatar HTTP/1.1
Host: hencoder.com
Content-Type: image/jpeg
Content-Length: 1575

JFIFHH9......

对应Retrofit的代码:

@POST("users/{id}/avatar")
Call<User>updateAvatar(@Path("id") Stringid, @BodyRequestBodyavatar);

...

RequestBodyavatarBody=RequestBody.create(MediaType.parse("image/jpeg"),avatarFile);
api.updateAvatar(id, avatarBody)

相应中返回⼆进制内容

HTTP/1.1 200 OK
content-type: image/jpeg
content-length: 1575

JFIFHH9......

Content-Length

指定Body的⻓度(字节)。

Transfer: chunked (分块传输编码Chunked Transfer Encoding)

⽤于当响应发起时,内容⻓度还没能确定的情况下。和Content-Length不同时使⽤。⽤途是尽早给出响应,减少⽤户等待。

格式:

HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked

4
Chun
9
ked Trans
12
fer Encoding
0

Location

指定重定向的⽬标URL

User-Agent

⽤户代理,即是谁实际发送请求、接受响应的,例如⼿机浏览器、某款⼿机App。

Range / Accept-Range

按范围取数据

Accept-Range: bytes响应报⽂中出现,表示服务器⽀持按字节来取范围数据

Range: bytes=<start>-<end>请求报⽂中出现,表示要取哪段数据

Content-Range:<start>-<end>/total响应报⽂中出现,表示发送的是哪段数据

作⽤:断点续传、多线程下载。

其他Headers

  • Accept:客户端能接受的数据类型。如text/html
  • Accept-Charset:客户端接受的字符集。如utf-8
  • Accept-Encoding:客户端接受的压缩编码类型。如gzip
  • Content-Encoding:压缩类型。如gzip

Cache

作⽤:在客户端或中间⽹络节点缓存数据,降低从服务器取数据的频率,以提⾼⽹络性能。

REST

REST的定义众说纷纭,没有统⼀答案。扔物线的观点:REST HTTP即正确使⽤HTTP。包括:

  • 使⽤资源的格式来定义URL
  • 规范地使⽤method来定义⽹络请求操作
  • 规范地使⽤status code来表示响应状态
  • 其他符合HTTP规范的设计准则