网络之HTTP协议

本文介绍了HTTP协议,它是典型应用层协议,还有其安全版。讲解了URL格式,以及urlencode编码与urldecode解码规则。详细阐述了HTTP协议格式,包括请求和响应的各部分,如首行、头部、空行、正文等,还介绍了常见请求方法、状态码和Header。


HTTP是典型的应用层协议,是目前最流行的通信协议,没有之一。
其衍生出了封装SSL协议的“安全版”:HTTPS协议,相对于传统的HTTP协议更为安全,但也是“相对的安全”。

只要保证通信传输一端发送时构造的数据, 在另一端能够正确的进行解析, 就是可以的,这种约定就是 应用层协议。是应用程序之间的沟通,这其中也涉及序列化与反序列化

序列化:将数据按照持久化存储或网络数据传输的格式进行排布。
反序列化:对数据以指定的协议进行解析。

虽然应用层协议是程序猿自定制的的。但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议)就是其中之一。


URL

平时我们俗称的 “网址” 其实就是 URL(统一资源定位符号(Uniform Resource Locator),其格式为:
在这里插入图片描述


urlencode编码 与 urldecode解码

/?: 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现。

比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

转义的规则如下:
将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做位,前面加上%,编码成%XY格式。

例如在百度上搜索C++,其URL为:
https://www.baidu.com/s?wd=C%2B%2B&rsv_spt=1
其中的%2B%2B就是转义字符,"%2B"就是"+"字符的转义字符。

网上编码解码的工具很多,这里简单介绍一个以便读者使用:【 http://tool.chinaz.com/Tools/urlencode.aspx


HTTP协议格式

通过分析数据包数据就可以明晰网络通信原理,这里我们使用fiddler工具进行抓包,其界面如下,从中就可以获得HTTP请求数据、响应数据等。
在这里插入图片描述

HTTP请求

请求格式为:请求首行请求头部空行正文

	//利用随意抓取的一个数据包举例:
GET http://neirong.funshion.com/airport/lua/fire.php?name=Fireman&cid=1001799 HTTP/1.1
Cache-Control: max-age=43200
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Funshion/1.0.0.1
Host: neirong.funshion.com
Connection: Keep-Alive
Pragma: no-cache

A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
Version: 3.3 (TLS/1.2)
Random: 18 75 2D C6 A0

请求首行

格式为:[方法] + [url] + [版本]

[GET] 
[http://neirong.funshion.com/airport/lua/fire.php?name=Fireman&cid=1001799] 
[HTTP/1.1]

请求头部(Header)

请求的属性, 冒号:分割的键值对。每组属性之间使用\n分隔;

Cache-Control: max-age=43200
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Funshion/1.0.0.1
Host: neirong.funshion.com
...

空行

请求头部信息遇到空行表示Header部分结束。(连续遇到2个\r\n就认为是头部信息结束了)

正文(Body)

空行后面的内容都是Body. 它允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度;


HTTP响应

在这里插入图片描述

响应首行

格式为: [版本号] + [状态码] + [状态码解释]

[HTTP/1.1] [200] [OK]

其他都与请求的元素相同,包含Header、空行、Body


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
TRACE追踪路径1.1
CONNECT要求用隧道协议连接代理1.1
LINK建立和资源之间的联系1.0
UNLINK断开联系1.0

其中最常用和常见的还是GETPOST方法。
在这里插入图片描述

HTTP状态码

/类别原因
1xx信息性状态码接收的请求正在处理
2xxSuccess(成功请求的数据处理完毕
3xxRedirection(重定向需要进行附加操作以完成请求
4xxClient Error(客户端错误)服务器无法处理请求
5xxServer Error(服务器错误)服务器处理请求出错

最常见的状态码, 比如 :
200(OK)
404(Not Found)
403(Forbidden,没有权限)
404(Not Found)
302(Redirect, 重定向)
504(Bad Gateway,坏的网关)


HTTP常见Header

  • Content-Type: 数据类型(text / html等)
  • Content-Length: Body的长度
  • Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
  • User-Agent: 声明用户的操作系统和浏览器版本信息;
  • referer: 当前页面是从哪个页面跳转过来的;
  • location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
  • Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Usage() {
	printf("usage: ./server [ip] [port]\n");
}
int main(int argc, char* argv[]) {
	if (argc != 3) {
		Usage();
		return 1;
	}
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0) {
		perror("socket");
		return 1;
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(argv[1]);
	addr.sin_port = htons(atoi(argv[2]));
	int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
	if (ret < 0) {
		perror("bind");
		return 1;
	}
	ret = listen(fd, 10);
	if (ret < 0) {
		perror("listen");
		return 1;
	}
	for (;;) {
		struct sockaddr_in client_addr;
		socklen_t len;
		int client_fd = accept(fd, (struct sockaddr*)&client_addr, &len);
		if (client_fd < 0) {
			perror("accept");
			continue;
		}
		char input_buf[1024 * 10] = {0}; // 用一个足够大的缓冲区直接把数据读完.
		ssize_t read_size = read(client_fd, input_buf, sizeof(input_buf) - 1);
		if (read_size < 0) {
			return 1;
		}
		printf("[Request] %s", input_buf);
		char buf[1024] = {0};
		const char* hello = "<h1>hello world</h1>";
		sprintf(buf, "HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello), hello);
		write(client_fd, buf, strlen(buf));
	}
	return 0;
}

编译, 启动服务. 在浏览器中输入 http://[ip]:[port], 就能看到显示的结果 "Hello World"
在这里插入图片描述

此处我们使用 9090 端口号启动了HTTP服务器. 虽然HTTP服务器一般使用80端口,但这只是一个通用的习惯. 并不是说HTTP服务器就不能使用其他的端口号.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值