有限状态机——逻辑单元内部的一种高效编程方法。
有的应用层协议头部包含数据包类型字段,每种数据类型可以映射为逻辑单元的一种执行状态,服务器可以根据它来编写相应的处理逻辑
独立的有限状态机
该状态机的每个状态都是相互独立的,状态之间没有相互转移。
state_machine(Package _pack) { PackageType _type=_pack.getType(); switch(_type) { case type_A: process_package_A(_pack); break; case type_B: process_package_B(_pack); break; } }
带状态转移的有限状态机
状态的转移需要状态机的内部驱动
STATE_MACHINE() { State curState=type_A; while(curState!=type_C) { Package _pack=getNewPackage();//获得一个新的数据包 switch(curState) { case type_A: process_package_state_A(_pack); curState=type_B; break; case type_B: process_package_state_B(_pack); curState=type_C; break; } } }
code
#include <sys/socket .h> #include <netinet/in.h> #include carpa/inet.h> #include <ssert.h> #include cstdio.h> #include <stdlib.h> #include <unistd.h> #include <orrno.h> #include <string.h> #include <fcnt1.h> #define BUFFER SIZB 4096/读缓冲区大小 /*主状态机的两种可能状态,分别表示当前正在分析请求行,当南正在分析头邮字段*/ enum CHECK_STATE { CRECK_STATE_REQUESTLINE=0,CHECK_STATE_HEADER }; /*从状态机的三种可能状态,即行的读取状态,分别表示:读取到一个完整的行、行出错和行数据尚目不完整*/ enum LINE_STATUS { LINE_OK=0,LINE_BAD,LINE_OPEN }; /*服务器处理了http请求的结来:NO_REQUEST表示请求不完整,需要续读取客户数据;GET_REOUEST表示获得了1个完警的客户清求; BAD_REQUEST表示客户请求有语法错误;FORBIDDEN_REOUEST表示客户对资源没有足够的访问权限;INTERNALL_ERROR表示服务器内部错误; CLOSED_CONECTION:表示家户端已经关闭连接*/ enum HTTP_CODE { NO_REQUEST,GET_REQUEST,BAD_REQUEST,FORBIDDEN_REQUEST,INTERNALL_ERROR,CLOSED_CONNECTON }; /*为了简化问题,我们没有给客户端发送一个完整的HTTP应答报文,面只是极据服务器的处理结果发送如下威功或失败信息*/ static const char* szret[]={"I get a correct result ", "Something wrong " }; /*从状态机,用干解析出一行内容,初始状态为OK,原始驱动力来自于buffer中新到来的数据*/ LINE_STATUS praseLine(char* buffer,int& checked_index, int& read_index) { char temp; /* checked index指向buffer (应用程序的读缓冲区)中当前正在分析的字节。read index指向buffer中客户数据的尾部的下一字节 buffer中第0-checkedindex字节都已分析完率,第checkedindex- (read index-11 字节由下面的循环挨个分析*/ for(;checked_index<read_index;++checked_index) { /*获得当前要分析的字节*/ temp=butfer[checked_index]; /*如果当前的字节是“ ”,即到车符,则说明可能读取到一个完整的行*/ if(temp==' ') { /*如果“ "是buff最后一个被读入的数据,这次没有读取到完整的一行*/ if((checked_index+1)==read_index) return LINE_OPEN; else if(temp[checked_index+1]==' ')//下一个字符是 ,读取到完整的一行 { buffer[checked_index++]='