概述
该代码为《LINUX高性能服务器编程》上的代码
为实现功能,设计了主状态机和从状态机:主状态机在内部调用从状态机。
从状态机的状态转换图如下:
代码如下
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4096
// 主状态机状态(功能的选择):正在分析请求行, 正在分析头部字段
enum CHECK_STATE
{
CHECK_STATE_REQUESTLINE = 0,
CHECK_STATE_HEADER
};
// 从状态机状态:读取到一个完整的行,行出错,行数据尚不完整
enum LINE_STATUS
{
LINE_OK = 0,
LINE_BAD,
LINE_OPEN
};
// 服务器处理HTTP请求的结果:
// NO_REQUEST 表示请求不完整,需要继续读取客户数据
// GET_REQUEST 表示获得了一个完整的客户请求
// BAD_REQUEST 表示客户请求有语法错误
// FORBIDDEN_REQUEST 表示客户对资源没有足够的访问权限
// INTERNAL_ERROR 表示服务器内部错误
// CLOSED_CONNECTION 表示客户端已经关闭连接
enum HTTP_CODE
{
NO_REQUEST,
GET_REQUEST,
BAD_REQUEST,
FORBIDDEN_REQUEST,
INTERNAL_ERROR,
CLOSED_CONNECTION
};
// 根据服务器处理结果发送如下成功或失败的消息
static const char *szret[] = {"I got a correct resultn", "Something wrong"};
// 从状态机,用于解析出一行内容
LINE_STATUS parse_line(char *buffer, int &checked_index, int &read_index)
{
char temp;
// checked_index指向buffer(应用程序的读缓冲区)中当前正在分析的字节
// read_index指向buffer中客户数据的尾部的下一字节
// buffer 中第0~checked_index字节都已分析完毕,第checked_index ~ (read_index - 1)字节有下面的循环进行分析
for (; checked_index < read_index; ++checked_index)
{
// 获得当前要分析的字节
temp = buffer[checked_index];
// 若当前字节是 回车符,说明可能读到一个完整的行
if (temp == 'r')
{
// 若 "r"碰巧是目前buffer中最后一个已经被读入的客户数据,则这次分析没读到一个完整的行,返回LINE_OPEN表示还要继续读取客户数据才能进行下一步分析
if ((checked_index + 1) == read_index)
{
return LINE_OPEN;
}
else if (buffer[checked_index + 1] == 'n')
{
// 若下一个字符是换行符,则表明成功读取到一个完整的行
buffer[checked_index++] = '