【php精品源码栏目提醒】:网学会员鉴于大家对php精品源码十分关注,论文会员在此为大家搜集整理了“Linux下Http_Server简要设计说明及源代码 - 其它资料”一文,供大家参考学习
Linux 下 Http Server 设计说明一、功能说明 1、本程序实现简易 httpServer,支持简单的文件请求以及 cgi 调用。
2、提供 200OK,403Forbidden,404Not Found,501Not Implemented几种类型消息响应。
3、支持多用户并发访问。
4、关于
php 解释器: 支持的功能: 、 1)允 许
php 脚本与 html 脚本嵌套 、支持简单的 echo,if,elseif,else,for,while 以及相互之间的嵌套 2) 、支持后缀自增运算符i,赋值操作包括字符串拼接,数值运算,数与字符串拼 3)接 不支持的功能: 、不支持 echo 后面跟多行作为输出 1) 、暂时不支持语句内的注释 2) 、与运算有关的暂时只支持,-操作,不支持,,/不支持类似i2 的操作 3) 、暂时不支持数组操作 4) 要求与限制: 1)、必须有ltphp 作为开头和gt作为结尾 、 2)放 在 if,else,for,while 中的语句无论有多少条都必须用花括号括起来 3)、暂时假定
php 文件的内容可以一次全部读入缓冲区二、相关知识 http 协议分为请求消息和响应消息,请求消息由三部分构成,请求行、消息报头、请求正文。
请求行格式为:Method Request-URI HTTP-Version CRLF 消息报头由一系列的 key-value 对组成,每行一个,格式为 key”:”空格value,消息报头与消息正文间有一单独空行。
响应消息类似,其中有一个状态码表示服务器处理的结果,常见有 200OK表示请求已被成功接收、理解、接受403Forbidden表示由于权限问题等服务器拒绝提供服务404NotFound表示请求的资源不存在等501Not Implemented则表示服务器端未实现相应的功能。
三、设计步骤 1、创建一个服务器,并监听既定的端口等待客户端的连接。
2、客户端发出连接请求后即创建一个子进程处理用户请求。
3、读取客户端发送的请求信息并获取相应的环境变量。
4、判断请求的文件是普通文件、cgi 程序还是
php 脚本文件,如果是普通文件则直接将文件内容 write 给客户端,如果是 cgi 程序创建一个新进程执行 cgi 程序,否则转 5。
5、识别出是
php 脚本文件后,调用 phpPraser 函数在相应的目录下将文件内容读入缓冲区假设一次可以全部读取,然后以空格、换行符等为分界符获取单个的字符串,并判断如果是ltphp 则获取后续内容直至遇到gt, 将获取的内容作为参数传递到
php 解释器 doPraser。
其中部分主要函数的功能解释如下:commPraser:负责以指定的分界符解析出变量,关键字,字符串常量,数值,并根据字符串的类型调用相应的解析函数。
doEcho:如果解析出的字符串时 echo,则说明后面是要输出的内容,调用 doEcho 解析之。
do_if,do_while,do_for 同理conditionPraser:如果字符串是关键字 if, while,for,则说明后面是条件表达式,调用conditionPraser 解析条件表达式并执行相应的操作do_assign:如果解析出的内容是要对某变量赋值,则调用 do_assign 函数四、源代码/ 本程序实现简易 httpServer,支持简单的文件请求、cgi 调用以及
php 解释器 提供 200OK 403Forbidden 404Not Found 501Not Implemented几种类型消息响应 /define _REENTRANTinclude ltunistd.hgtinclude ltstdlib.hgtinclude ltstdio.hgtinclude ltsys/types.hgtinclude ltsys/stat.hgtinclude ltsys/socket.hgtinclude ltnetinet/in.hgtinclude ltarpa/inet.hgtinclude ltstring.hgtinclude ltpthread.hgtinclude ltfcntl.hgtinclude ltsignal.hgtinclude ltiostreamgtinclude ltstringgtinclude ltmapgtusing namespace stddefine SIZE 512define SSIZE 64define VARIABLE 1define CONSTANT 2define KEY_WORD 3define KEY_WORD_NUM 11define ERROR -1int portchar rootDoccharkeywordsSSIZEquotechoquotquotforquotquotwhilequotquotifquotquotelseifquotquotelsequotquotbreakquotquotcontinuequotquotreturnquotquotswitchquotquotcasequotquotdefaultquot//mapltstringstringgt mapStr //定义一个存放
php 变量名及对应 value 的 map 数组错误!这个变量还不能定义成全局变量,要考虑到多用户的情况int getInfoconst char destconst char srcchar resultinline int isSubStrconst char destconst char srcint ampleftint amprightinline void getSubStrchar bufferint ichar destvoid getEnvchar buffervoid processchar bufferint client_fdinline void clear_line_breakchar bufferint ampiint leninline int isKeyWordchar tmpinline bool isDigitalchar strint commPraserchar strint lenint ampichartmpinline int getVarchar srcchar destmapltstringstringgt ampmapStr //mapStr 必须作为引用传递,否则所做的改变无效int conditionPraserchar strint lenint imapltstringstringgt ampmapStrinline void doEchoFILE tmpfpchar strint lenint ampimapltstringstringgt ampmapStrinline void getCrossBodychar strint lenint ampichar mainBodyvoid insertVarchar keychar varmapltstringstringgt ampmapStrvoid do_whileFILE tmpfpchar strint lenint ampimapltstringstringgt ampmapStrvoid do_forFILE tmpfpchar strint lenint ampimapltstringstringgt ampmapStrvoid do_ifFILE tmpfpchar strchar tmpint lenint ampimapltstringstringgt ampmapStrvoid do_assignchar keychar strmapltstringstringgt ampmapStrvoid doPraserFILE tmpfpchar strint lenint imapltstringstringgt ampmapStrvoid phpPraserint client_fdFILE fpchar buffervoid transferint client_fdchar pathvoid logconst char infint lineint tag0/ 功能:查询 src 中是否有 key 值 dest,如果有则取出对应的 value 存放到 result 中 返回值:返回 0 表示成功查找到相应 key,-1 表示查找失败 /int getInfoconst char destconst char srcchar result int leftrightj ifisSubStrdestsrcleftright 0 forjleftjltrightj resultj-leftsrcj resultj-left0 return 0 return -1/ 功能: 判断 dest 中所存放的 key 是否是 src 的子串,是则将对应的 value 起止下标存入 left和 right 中 返回值:0 成功,-1 失败 /inline int isSubStrconst char destconst char srcint ampleftint ampright char tmpSIZE int lensstrlensrc int lendstrlendest int ijk fori0iltlens-lendi forjijltilendj tmpj-isrcj tmpj-i0 ifstrcasecmpdesttmp 0 leftilend2 //2 表示一个冒号和一个空格 rightleft whilesrcright n right return 0 //成功获取环境变量 return -1/ 功能:获取 http 请求行中的 REQUEST_METHOD 等信息 /inline void getSubStrchar bufferint ichar dest int j0 whilebufferi destjbufferi i destj0/ 从客户端的请求信息中获取环境变量等信息 /void getEnvchar buffer int leftright char tmpSIZE const char cLenquotcontent-lengthquot const char cTypequotcontent-typequot int i0 whilebufferi tmpibufferi i tmpi0 setenvquotREQUEST_METHODquottmp1 getInfocLenbuffertmp setenvquotCONTENT_LENGTHquottmp1 getInfocTypebuffertmp setenvquotCONTENT_TYPEquottmp1/ 处理客户请求,包括请求普通文件以及调用 cgi /void processchar bufferint client_fd char envgetenvquotREQUEST_METHODquot char tmpSIZE char requestDocSIZE char queryStrSIZE ifenv NULL strcasecmpenvquotPOSTquot 0 ampamp strcasecmpenvquotGETquot 0 ampamp strcasecmpenvquotHEADquot 0 //目前只检测三种方式 const char respondquotHTTP/1.1 501 Not Implementedrncontent-type:text/htmlcharsetgb2312rnrnlthtmlgtlth1gt501 Not Implementedlt/h1gtlt/htmlgtrnquot writeclient_fdrespondstrlenrespond closeclient_fd exit1 int jstrlenenv1i0 ifbufferj / j whilebufferj ampamp bufferj //获取请求行中quot/filenameparkfangquot并以为界将其分离开来从而获取 QUERY_STRING requestDocibufferj requestDoci0 i0 ifbufferj j whilebufferj queryStribufferj queryStri0 setenvquotQUERY_STRINGquotqueryStr1 sprintftmpquotrequestDoc: squotrequestDoc logtmp__LINE__ sprintftmpquotqueryStr: squotgetenvquotQUERY_STRINGquot char pathSIZE sprintfpathquots/squotrootDocrequestDoc logpath__LINE__2 ifaccesspathF_OK -1 //请求的文件不存在 const char respondquotHTTP/1.1 404 Not Foundrncontent-type:text/htmlcharsetgb2312rnrnlthtmlgtlth1gt404 Not Foundlt/h1gtlt/htmlgtrnquot writeclient_fdrespondstrlenrespond closeclient_fd exit1 ifaccesspathR_OK -1 //禁止访问 const char respondquotHTTP/1.1 403 Forbiddenrncontent-type:text/htmlcharsetgb2312rnrnlthtmlgtlth1gt403 Forbiddenlt/h1gtlt/htmlgtrnquot writeclient_fdrespondstrlenrespond closeclient_fd exit1 ifaccesspathX_OK 0 //调用可执行文件有点小问题,某些非可执行文件在创建时也可能被赋予了可执行的权限,因此要采用一个更准确的判断方法 const char respondquotHTTP/1.1 200 OKrnquot writeclient_fdrespondstrlenrespond int pid ifpidfork 0 dup2client_fd1 execlpath0 else exit0 else //请求普通文件 transferclient_fdpath / 忽略不相关的字符——需要再斟酌以下是否要忽略引号 /inline void clear_line_breakchar bufferint ampiint len whilei lt lenampampbufferi bufferi nbufferi bufferi bufferi bufferi bufferi tbufferi bufferi quot i / 判断 tmp 串是否为所支持的关键字 /inline int isKeyWordchar tmp int i fori0iltKEY_WORD_NUMi ifstrcmpkeywordsitmp 0 break ifiltKEY_WORD_NUM return 1 return 0/ 判断一个字符串是不是一个整数目前只支持整数,方法上有瑕疵,32 位 int 的范围是-2147483648~2147483647但奇怪的是给 int 型数据赋下限值会出现警告g编译 实际上
php 支持的可进行四则运算的数据长度远不只 10 位 /inline bool isDigitalchar str int ilenstrlenstr fori0iltleni ifstri gt 0ampampstri lt 9 break ifiltlen return false ifstr0 -ampamplen gt 11str0 -ampamplen gt 10 return false iflen 10ampampstrcmpstrquot2147483647quot gt 0 return false iflen 11ampampstrcmpstrquot-2147483648quot gt 0 return false return true/ 获取关键字或变量不包括串和数,如果遇到引号,则该函数不能前进如果其他地方doEcho不能跳过引号,将会造成死循环已修改 该函数可以解析负数,如-4 等,这意味着遇到负号不能跳过,但是这样会导致i--被当作一个变量而不是运算,因此要确保负号是第一个出现才接收ik /int commPraserchar strint lenint ampichar tmp int j0ki clear_line_breakstrilen ifi gt lenstr NULL return ERROR whilei lt lenampampstri stri _stri gt0ampampstri lt 9stri -ampampik stri gt aampampstri lt zstri gt Aampampstri lt Z // 是 否 要 加 上 不 等 于n tmpjstri tmpj0 iftmp0 //变量 return VARIABLE else ifisKeyWordtmp return KEY_WORD else return CONSTANT / 从 map 中根据 key 值获取对应的 value获取失败则返回-1 /inline int getVarchar srcchar destmapltstringstringgt ampmapStr mapltstringstringgt::iterator itermapStr.begin whileiter mapStr.endampampstrcmpsrciter-gtfirst.c_str 0 iter ifiter mapStr.end return -1 strcpydestiter-gtsecond.c_str return 0/ 解析 if...elseif...elseforwhile 中的条件判断表达式,并根据解析结果返回 1条件成立,0条件不成立 /int conditionPraserchar strint lenint imapltstringstringgt ampmapStr // 条 件 表 达 式 判断函数用于判断 if,while,for 中的条件是否成立 char key1SIZEkey2SIZEvar1SIZEvar2SIZE char tmpSIZE char logtmpSIZE int jretret1 memsetkey10sizeofkey1 memsetkey20sizeofkey2 memsetvar10sizeofvar1 memsetvar20sizeofvar2 retcommPraserstrlenikey1 //注意:对于需要重复解析的代码部分,需要保存代码入口地址 sprintflogtmpquotconditionPraser: keysquotkey1 loglogtmp__LINE__ ifret CONSTANT //条件表达式为常量 ifstrcmpkey1quot0quot 0 return 0 else return 1 else ifret VARIABLE //如果是变量则看是否是要将其和另一个量比较,还是只要检查它本身的值 char signSSIZE j0 whilei lt lenampampstri gtstri ltstri stri stri i //第一个 while 是为了到达比较运算符或者右括号只检查变量自身的值的情况 whilei lt lenampampstri gtstri ltstri stri signjstri signj0 ret1getVarkey1var1mapStr //根据 var 获取 value ifi gt len //i gt len,说明是检查变量自身的值 //使用 map 检查变量的值,并返回结果 ifstrcmpvar1quot0quot 0var10 0 //值为空或者为 0,问题是使用未定义的
php 变量进行判断时不知道是什么效果 return 0 return 1 memsettmp0sizeoftmp retcommPraserstrlenitmp ifret VARIABLE strcpykey2tmp retgetVarkey2var2mapStr else ifret CONSTANT strcpyvar2tmp / 说明:程序运行到这里时, 说明是两个量在进行比较以决定执行相应的代码体,假设比较的形式为 variable1 gt variable2 则,函数接受的参数 key1 就是 variable1,var1 为 variable1 的值 key2 是 variable2,var2 为 variable2 的值 / sprintflogtmpquotconditionPrase:key1svar1skey2svar2squotkey1var1key2var2 loglogtmp__LINE__ ifvar10 gt0ampampvar10 lt9 //表达式左边是数,当然,判断的方法太局限了,数也可能是字符串那么能否都当作字符串处理呢 ifret1 0 当然, //只有在成功获取 variable1 的值时才能执行,除非有语法错误,否则一定会执行 int digital_leftatoivar1 int digital_rightatoivar2 ifdigital_left gt digital_rightampampstrcmpsignquotgtquot 0 digital_left gt digital_rightampampstrcmpsignquotgtquot 0 digital_left digital_rightampampstrcmpsignquotquot 0 digital_left lt digital_rightampampstrcmpsignquotltquot 0 digital_left lt digital_rightampampstrcmpsignquotltquot 0 digital_left digital_rightampampstrcmpsignquotquot 0 return 1 return 0 else //字符串 ifret1 0 retstrcmpvar1var2 ifret 0ampampstrcmpsignquotquot 0 ret 0ampampstrcmpsignquotquot 0 ret -1ampampstrcmpsignquotltquot 0 ret 1ampampstrcmpsignquotgtquot 0 return 1 return 0 / 函数功能,获取 if...elseif...elseforwhile 函数的执行代码体,注意执行完后指针会跳过该代码体 getBody 函数已同 crossBrace 合并的缺陷在于,如果 if 语句里面嵌套了其他的 for 之类的含有的代码,则不能正确获取代码体已改正, 另外,do_if 的实现风格与 do_for 和 do_while 也不一样 /void getCrossBodychar strint lenint ampichar mainBody int num1j0 whileiltlen ampamp stri i i //跳过第一个大括号 whileiltlen .
上一篇:
php5.3.5配置教程(包括phpMyadmin3.4.0)
下一篇:
法律专业开题报告范文