【web server】HTTP协议如何解析or封装

HTTP协议(关于HTTP协议之前的文章有写过)如何解析or封装?
首先来看下这块的处理过程,有一个整体的概念:

void Http::process() {
	//主线程读完数据后,来到这里处理
	HTTP_CODE read_ret = process_read();
	if (read_ret == NO_REQUEST) {
		//解析完数据发现客户端没有请求,直接退出
		return ;
	}
	//如果有请求,根据刚才解析的结果,封装报文
	bool write_ret = process_write(read_ret);
	if (!write_ret) {
		close_conn();
	}
	//告诉主线程,报文已经封装好了,可以发送了!
	modfd(s_iEpollfd, m_iSockFd, EPOLLOUT);
}

主线程读数据:

bool Http::read() {
	if (m_read_idx >= READ_BUFFER_SIZE) {
		return false;
	}
	int bytes_read = 0;
	while (true) {
		bytes_read = recv(m_iSockFd, m_read_buf + m_read_idx, READ_BUFFER_SIZE - m_read_idx, 0);
		if (bytes_read == -1) {
			if (errno == EAGAIN || errno == EWOULDBLOCK) {
				break;
			}
			return false;
		} else if (bytes_read == 0) {
			return false;
		}
		m_read_idx += bytes_read;
	}
	return true;
}

读到的正是这样一行一行的数据:
在这里插入图片描述
将数据循环读到m_read_buf中,接着开始处理读到的数据:

Http::HTTP_CODE Http::process_read() 
{
	...
	while (...) {
		//拿到每一行数据
		text = get_line();
		switch (m_check_state) {
				case CHECK_STATE_REQUESTLINE: {
					//处理请求行
					parse_request_line(text);
					...
					break;
				}
				case CHECK_STATE_HEADER: {
					//处理头部字段
					parse_headers(text);
					...
					break;
				}
				default: {
					return INTERNAL_ERROR;
				}
		}
	}
}

用一个变量m_check_state来表示分析状态:

enum CHECK_STATE {
	CHECK_STATE_REQUESTLINE = 0, //当前正在分析请求行
	CHECK_STATE_HEADER	//当前正在分析头部字段
};

以便在parse_request_line之后改变状态,之后进入parse_headers中处理。

分析请求行和头部字段,可以了解到当前客户端要请求的资源的信息以及客户端一些信息。

若在解析的过程中发现客户端请求了页面,则在服务端找到该文件,并写入内存,等待发送,比如在do_request

Http::HTTP_CODE Http::do_request() {
	...
	//若解析出的请求行中有“/”则默认返回index.html首页面
	if (strcmp(m_url, "/") == 0) {
		strcat(m_url, "index.html");
	}
	//处理其他,比如服务端没有资源,返回404.html 等等
	...
	//若资源存在,读到内存中,等待发送
}

解析请求行和头部字段后,发现需要返回资源,便按照响应报文的格式封装报文并发送:

bool Http::process_write(HTTP_CODE ret) {
	switch (ret) {
		...
		case NO_RESOURCE: {
			add_status_line(404, error_404_title);
			add_headers(strlen(error_404_form));
			add_content(error_404_form);
			break;
		}
		case FILE_REQUEST: {
			add_status_line(200, ok_200_title);
			add_headers(file.size());
			add_content(file);
			break;
		}
		default: {
			return false;
		}
	}
	return true;
}

add_status_line用来添加状态行,add_headers用来添加头部字段(之后添加一行空行),add_content用来添加内容。

至此,响应报文也就封装完成了,之后通知主线程发送报文即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高二的笔记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值