宝哥软件园

PHP实现动态网服务器方法

编辑:宝哥软件园 来源:互联网 时间:2021-09-08

以下内容通过图文并茂的方式介绍服务器端编程语言(专业超文本预处理器的缩写)实现动态网服务器的方法,具体内容如下:

本文所实现的服务器仅仅是演示和理解原理所用,力求简单易懂。有兴趣的朋友可以继续深入改造

要是现实一个网服务器,那么就需要大概了解网服务器的运行原理。先从静态的文本服务器开始,以访问网服务器的1.html为例

1.客户端通过发送一个超文本传送协议(超文本传输协议的缩写)请求到服务器,如果服务器监听的端口号是9002,那么在本机自身测试访问的地址就是http://localhost:9002/1.html。

2.服务器监听着9002端口,那么在收到请求了请求之后,就能从超文本传送协议(Hyper Text Transport Protocol的缩写)头头中获取到请求里需要访问的上呼吸道感染资源在网目录中的位置。

3.服务器读取需要访问的资源文件,然后填充到超文本传送协议(超文本传输协议的缩写)的实体中返回给客户端。

示意图如下:

php?phpclass web_config { //监听的端口号const PORT=9003//项目根目录const WEB _ ROOT='/user/周梦康/Documents/html ';}类服务器{私有$ ip私有$ port public function _ _ construct($ IP,$ port){ $ this-IP=$ IP;$ this-port=$ port;$ this-await();}私有函数await(){ $ SOCK=socket _ create(AF _ INET,SOCK_STREAM,SOL _ TCP);if ($sock 0) { echo 'Error: ' .socket _ strerror(socket _ last _ error()). n ';} $ret=socket_bind($sock,$this-ip,$ this-port);if(!$ret) { echo 'BIND FAILED: ' .socket _ strerror(socket _ last _ error()). n ';退出;}回显"确定 n ";$ ret=socket _ listen($ sock);if($ ret 0){ echo ' LISTEN失败: ' .socket _ strerror(socket _ last _ error()). n ';} do { $ new _ sock=null尝试{ $ new _ sock=socket _ accept($ sock);} catch(Exception $ e){ echo $ e-getMessage();回应"接受失败:"。socket _ strerror(socket _ last _ error()). n ';}尝试{ $ request _ string=socket _ read($ new _ sock,1024);$ response=$ this-output($ request _ string);socket_write($new_sock,$ response);socket _ close($ new _ sock);} catch(Exception $ e){ echo $ e-getMessage();回应"读取失败:"。socket _ strerror(socket _ last _ error()). n ';} } while(TRUE);}/* * * @ param $ request _ string * @ return string */private函数输出($request_string){ //静态GET /1.html HTTP/1.1.$request_array=explode(',$ request _ string);if(count($ request _ array)2){ return $ this-not _ found();} $ uri=$ request _ array[1];$ filename=WeB _ config : WeB _ ROOT .$ uri回显请求:$文件名“ n”;//静态文件的处理if(file _ exists($ filename)){ return $ this-add _ header(file _ get _ contents($ filename));} else { return $ this-not _ found();} } /** * 404 返回* @返回字符串*/私有函数Not _ Found(){ $ content=' h1文件未找到/h1 ';返回"未找到HTTP/1.1 404文件 r n内容-类型:文本/html r n内容-长度:"。strlen($content ).rnrn ' .$ content} /** *加上头信息* @ param $ string * @ return string */private函数add _ header($ string){ return ' HTTP/1.1 200 OK r n内容长度: ' .strlen(字符串).rn服务器:孟康rnrn .$ string}}$server=新服务器(' 127.0.0.1 ',web _ config :端口);

代码已经上传github https://github。com/周梦康/PHP/tree/master/PHP-web服务器/静态

如上代码所述,只要在终端执行该文件,那么一个静态的网服务器就启动啦。

下图为我访问我网目录下的1.jpg文件的截图

简单的静态网服务器已经完成了,下面的问题就是怎么让其支持动态内容的输出了。是不是只需要在网服务器内部执行完某个程序之后,把得到的结果返回给客户端就行呢?但是这样网服务器的代码就和业务代码耦合在一起了,怎么解决一个网服务器,可以运用在各个业务场景下呢?

公共网关接口的出现解决了这一问题。那么公共网关接口是什么呢?下面这段话复制的:

CGI是外部应用程序(CGI程序)和Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的过程。CGI规范允许网络服务器执行外部程序,并将它们的输出发送到网络浏览器。CGI把一组简单的Web静态超媒体文档变成了一个完整的新型交互媒体。

我晕了,比如我们正在使用的PHP的全局变量$_SERVER['QUERY_STRING']是由Web服务器通过CGI协议传递的。例如,在Nginx中,也许您还记得这个fastcgi配置

复制代码如下: fastcgi _ param query _ string $ query _ string;

是的,nginx将其全局变量$query_string传递给了fastcgi_param的环境变量。

接下来,我们还使用cgi的QUERY_STRING作为桥梁,将客户端请求的uri中的信息传递给CGI程序。通过putenv将QUERY_STRING保存在请求的环境变量中。

我们同意在网络服务器中访问的资源是动态的。cgi后缀,类似于在nginx中配置location来查找php脚本。是检查是否应该请求cgi程序的规则。为了区别于Web服务器,我编写了一个cgi程序,在C中查询用户信息,根据用户id查询用户数据。

一般访问逻辑如下

演示代码地址:https://github.com/周梦康/PHP/tree/master/PHP-web server/dynamic

如果您想要运行演示,您需要执行以下操作

1.修改config.php的项目根目录

2.编译cgi-demouser.c,编译命令gcc-o user.cgi user . c,然后将user . CGI文件放在您配置的项目根目录下

3.在终端执行PHP start.php,这样网络服务器就启动了

4.通过http://localhost :9003/user . CGI?Id=1可以访问并看到以下效果

其实我只是在静态服务器的基础上做了一些cgi的判断,也就是请求转发的处理,把github上三个文件的代码合并成一个文件大家看

php?phpclass web_config { //监听的端口号const PORT=9003//项目根目录const WEB _ ROOT='/user/周梦康/Documents/html ';//系统支持的计算机生成图像程序的文件扩展名const CGI _ EXTENSION=' cgi}类服务器{私有$ ip私有$ port public function _ _ construct($ IP,$ port){ $ this-IP=$ IP;$ this-port=$ port;$ this-await();}私有函数await(){ $ SOCK=socket _ create(AF _ INET,SOCK_STREAM,SOL _ TCP);if ($sock 0) { echo 'Error: ' .socket _ strerror(socket _ last _ error()). n ';} $ret=socket_bind($sock,$this-ip,$ this-port);if(!$ret) { echo 'BIND FAILED: ' .socket _ strerror(socket _ last _ error()). n ';退出;}回显"确定 n ";$ ret=socket _ listen($ sock);if($ ret 0){ echo ' LISTEN失败: ' .socket _ strerror(socket _ last _ error()). n ';} do { $ new _ sock=null尝试{ $ new _ sock=socket _ accept($ sock);} catch(Exception $ e){ echo $ e-getMessage();回应"接受失败:"。socket _ strerror(socket _ last _ error()). n ';}尝试{ $ request _ string=socket _ read($ new _ sock,1024);$ response=$ this-output($ request _ string);socket_write($new_sock,$ response);socket _ close($ new _ sock);} catch(Exception $ e){ echo $ e-getMessage();回应"读取失败:"。socket _ strerror(socket _ last _ error()). n ';} } while(TRUE);}/* * * @ param $ request _ string * @ return string */private函数输出($request_string){ //静态GET /1.html HTTP/1.1.//动态GET /user.cgi?id=1 HTTP/1.1.$request_array=explode(',$ request _ string);if(count($ request _ array)2){ return " ";} $ uri=$ request _ array[1];回显请求:web_config:WEB_ROOT .$uri . n ';$ query _ string=null if($ uri=='/fav icon。ico '){ return " ";} if (strpos($uri,'?')){ $uriArr=explode('?',$ uri);$ uri=$ Uriarr[0];$query_string=isset($uriArr[1])?$ UriArr[1]: null;} $ filename=WeB _ config : WeB _ ROOT .$ uri if($ this-CGI _ check($ uri)){ $ this-set _ env($ query _ string);$ handle=popen(WeB _ config : WeB _ ROOT .$uri," r ");$ read=stream _ get _ contents($ handle);PC丢失($ handle);返回$ this-add _ header($ read);} //静态文件的处理if(file _ exists($ filename)){ return $ this-add _ header(file _ get _ contents($ filename));} else { return $ this-not _ found();} } /** * 设置环境变量给计算机生成图像程序使用* @ param $ query _ string * @ return bool */private function set _ env($ query _ string){ if($ query _ string==null){ return false;} if (strpos($query_string,'='){ put env(' QUERY _ STRING=').$ query _ string);} } /** * 判断请求的上呼吸道感染是否是合法的计算机生成图像资源* @ param $ uri * @返回bool */private函数CGI _ check($ uri){ $ info=path info($ uri);$ extension=isset($ info[' extension '])?$info['扩展]: null;if($ EXTENSION in _ array($ EXTENSION,explode(',',web _ config : CGI _ EXTENSION)){返回true}返回false} /** * 404返回* @返回字符串*/私有函数Not _ Found(){ $ content=' h1文件未找到/h1 ';返回"未找到HTTP/1.1 404文件 r n内容-类型:文本/html r n内容-长度:"。strlen($content ).rnrn ' .$ content} /** *加上头信息* @ param $ string * @ return string */private函数add _ header($ string){ return ' HTTP/1.1 200 OK r n内容长度: ' .strlen(字符串).rn服务器:孟康rnrn .$ string}}$server=新服务器(' 127.0.0.1 ',web _ config :端口);以上就是本文的全部内容,希望大家喜欢。

更多资讯
游戏推荐
更多+