HTTP协议&实现一个最简单的HTTP服务器

1.HTTP协议(超文本传输协议)是一个应用层的协议
2.认识URL
平时我们所说的网址就是URL
urlencode和urldecode
像/?:等这样的字符,已经被url当作特殊意义理解了。因此这些字符不能随便出现。比如,某个参数中需要带有这写特殊字符,就必须先对特殊字符进行转义。
转移的规则如下:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。urlencode就是起的编码作用。
urldecode就是urlencode的反过程,解码已编码的url字符串。
3.HTTP协议格式
3.1HTTP请求

  • 首行:[方法]+[url]+[版本]
  • Header:请求的属性,冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束。
  • Body:空行后面的内容都是Body。Body允许为空字符串,如果Body存在,则在Header中会有一个Content-Length属性来标识Body的长度。

3.2HTTP响应

  • 首行:[版本号]+[状态码]+[状态码解释]
  • Header:请求的属性,冒号分隔的键值对,每组属性之间使用\n分隔,遇到空行表示Header部分结束。Content-Length属性来标识Body的长度;如果服务器返回了一个html页面,那么html页面内容就是在body中。

3.3http数据的解析过程
1.获取http头部,(首行+头部)
首行中包含url可以知道客户端请求什么资源,GET请求还可以获取到提交的数据
首行中包含的协议版本:拿到版本就可以针对不同版本的特性进行处理
2.解析头部
可以获取正文有多长,正文是什么类型的数据
3.获取正文进行处理(通常将正文交给子进程处理)

4.HTTP的方法
GET:获取资源
POST:传输实体主体
PUT:传输文件
HEAD:获得报文头部
DELETE:删除文件
其中最常用的就是GET和POST方法
5.HTTP的状态码

1XX 信息性状态码(接受的请求正在处理)
2XX 成功状态码(请求正常处理完毕)
3XX 重定向状态码(需要进行附加操作以完成请求)
4XX 客户端错误状态码(服务器无法处理请求)
5XX 服务器状态错误码(服务器处理请求出错)

最常见的状态码:比如200(ok),404(Not Found),403(Forbidden),302(重定向),504等。
6.HTTP常见Header

  • Content-Type:数据类型(text/html等)。
  • Content-Length:Body的长度。
  • Host:客户端告知服务器,所请求资源是在哪个主机的哪个端口上;
  • User-Agent:声明用户的操作系统和浏览器版本信息。
  • referer:当前页面是从哪个页面跳过来的。
  • location:搭配3XX状态码使用,告诉客户端接下来要去哪里访问。
  • Cookie:用于在客户端存储少量信息,通常用于实现会话的功能。

7.实现一个最简单的HTTP服务器
实现一个最简单的http服务器,只在ww网页上输出“hello world”;

#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 = "

hello world

"
; 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],就可以看到结果显示在页面上。

你可能感兴趣的:(HTTP协议&实现一个最简单的HTTP服务器)