国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
古老的CGI與Web開發(fā)
C++后臺(tái)實(shí)踐:古老的CGI與Web開發(fā)
本文寫給C/C++程序猿,也適合其他對(duì)歷史感興趣的程序猿
=============================================
談到web開發(fā),大家首先想到的PHP、JavaEE/JSP、.NET/ASP、Ruby on rails、Python的Django等等??芍^百花齊放,你一般不會(huì)想到C++和Web開發(fā)有什么關(guān)系,但其實(shí)動(dòng)態(tài)網(wǎng)頁的開發(fā)(web開發(fā))可是在這些動(dòng)態(tài)網(wǎng)頁語言誕生之前就存在了的。所以C/C++也是可以做web開發(fā)的,它利用的技術(shù)是——CGI。
在天地初開,混沌未分之時(shí),動(dòng)態(tài)網(wǎng)頁語言尚未出世,要實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)站依賴的就是CGI。谷歌/百度一下CGI,可能會(huì)出現(xiàn)很多名詞:CGI腳本、CGI程序、CGI標(biāo)準(zhǔn)等等。其實(shí)這些都是站在不同角度來說的,CGI即Common Gateway Interface的縮寫,直譯為“通用網(wǎng)關(guān)接口”。第一次聽這個(gè)名字,我也不知道是個(gè)什么鬼東西。歸根結(jié)底 CGI就是一個(gè)接口協(xié)議。協(xié)議就是大家公認(rèn)的一套標(biāo)準(zhǔn)(叫CGI標(biāo)準(zhǔn)也可以),比如網(wǎng)絡(luò)協(xié)議。大家都遵守一套標(biāo)準(zhǔn),就減少了溝通的難度。進(jìn)行CGI開發(fā),就是編寫一個(gè)CGI可執(zhí)行程序。其實(shí)各種語言都可以編寫CGI,不但Java、Python、PHP、C#……可以,而且Shell也可以。當(dāng)然C和C++也可以。由于早期CGI很多是由Perl(腳本語言)開發(fā)的,所以CGI程序也稱CGI腳本,其實(shí)這個(gè)稱呼不一定準(zhǔn)確。因?yàn)镃++編譯出的可執(zhí)行文件同樣可以是CGI。
在PHP和Java大行其道的今天,很多人看來用C++編寫CGI是幾乎淘汰的技術(shù)了(其實(shí)這到不然,只是比較小眾罷了)。所以如果你對(duì)C/C++感興趣或者對(duì)歷史感興趣都可以閱讀本文。
一次網(wǎng)頁請求與響應(yīng)
在進(jìn)行網(wǎng)頁瀏覽時(shí),通常就是通過一個(gè)URL請求一個(gè)網(wǎng)頁,然后服務(wù)器返回這個(gè)網(wǎng)頁文件給瀏覽器。瀏覽器在本地解析該文件渲染成我們看到的網(wǎng)頁。然而通常我們看到的網(wǎng)頁不是靜態(tài)網(wǎng)頁,也就是說在服務(wù)端是沒有這個(gè)網(wǎng)頁文件,它是在網(wǎng)頁請求的時(shí)候動(dòng)態(tài)生成的,比如PHP/JSP網(wǎng)頁。依據(jù)你請求的參數(shù)不同,所返回的內(nèi)容不同。
同理,如果是請求一個(gè)CGI程序的時(shí)候(比如在瀏覽器直接輸入CGI程序的URL,或者提交表單的時(shí)候發(fā)送給CGI程序),CGI程序負(fù)責(zé)解析從前端傳遞過來的參數(shù),理解它的意圖然后返回?cái)?shù)據(jù),比如返回HTML、XML或JSON等。
WARNNING:Apache默認(rèn)沒有打開CGI的支持,需要進(jìn)行CGI的配置。具體方法可以自行百度。
預(yù)備前端知識(shí)
假設(shè)你是一個(gè)C++程序員,你可能對(duì)前端不熟(OK,我也不熟),在接下來的講述之前,你要先掌握一些預(yù)備的前端知識(shí)(盡量少講前端),你不需要知道如何渲染出一個(gè)美輪美奐的網(wǎng)頁,但你需要知道前、后端如何交互。前端頁面如何發(fā)送數(shù)據(jù),一個(gè)普通的HTML頁面通常的做法,你只需知道如下幾種:
form表單提交(html原生)
js操縱下的表單提交
js通過Ajax請求數(shù)據(jù)
這里知講第一種(最簡單的):
[html] view plain copy
<h1>表單提交</h1>
<form action="/cgi-bin/hello.cgi" method="get">
<table>
<tr>
<td>用戶名:</td>
<td><input name="username"/></td>
</tr>
<tr>
<td>密碼:</td>
<td><input name="password"/></td>
</tr>
<tr>
<td><input type="submit" value="OK"/></td>
</tr>
</table>
</form>
form標(biāo)簽的action屬性的值表示的就是表單要提交到url,即表單提交以后要跳轉(zhuǎn)的頁面(Ajax可以達(dá)到無跳轉(zhuǎn)拉取數(shù)據(jù),刷新頁面),這里action屬性值的是cgi程序的url地址。(WARNNING:/ 對(duì)應(yīng)的是網(wǎng)站根目錄,而不是Linux文件系統(tǒng)根目錄哦)。method屬性表示數(shù)據(jù)請求方式,有兩種:get和post。不贅述。
我輸入用戶名jellywang,密碼123456之后,點(diǎn)擊OK按鈕,即向 當(dāng)前域名/cgi-bin/hello.cgi 的程序序提交了表單,并且攜帶參數(shù)username=jellywang。然后頁面會(huì)跳轉(zhuǎn)到這個(gè)cgi(就像普通網(wǎng)頁跳轉(zhuǎn),瀏覽器地址欄更新一樣)。
如果是get請求。那么瀏覽器地址欄的URL看起來像這樣:localhost:/cgi-bin/hello.cgi?username=jelly&password=123456。很顯然這是一種不夠安全的方式,所以我們還可以使用post請求。這樣地址欄就看不到這種提交的參數(shù)了。(其實(shí)post也不夠安全,不鼓勵(lì)直接提交明文密碼的方式,本文僅作示例,安全登錄不上本文重點(diǎn))
環(huán)境變量與CGI處理
當(dāng)前端頁面通過get或post方法向cgi程序提交了數(shù)據(jù)以后,那么接下來cgi程序該如何解析呢?答案是環(huán)境變量。無論是Linux系統(tǒng)或Windows系統(tǒng)都有環(huán)境變量的概念。Linux用戶在配置很多環(huán)境的時(shí)候,都不得不在系統(tǒng)配置文件中和環(huán)境變量打交道。CGI程序即是通過從環(huán)境變量中取值來獲得參數(shù)的。這里介紹幾個(gè)環(huán)境變量(更多的請自行百度):
REQUEST_METHOD
前端頁面數(shù)據(jù)請求方式:get/post
QUERY_STRING
采用GET時(shí)所傳輸?shù)男畔?div style="height:15px;">
CONTENT_LENGTH
STDIO中的有效信息長度
SCRIPT_NAME
所調(diào)用的CGI程序的名字
SERVER_NAME
服務(wù)器的IP或名字
SERVER_PORT
主機(jī)的端口號(hào)
這些環(huán)境變量是從何而來,是誰定義的?是Linux嗎?POSIX嗎?當(dāng)然不是。這里就要再次聲明一下CGI是一個(gè)接口協(xié)議,這些環(huán)境變量就是屬于該協(xié)議的內(nèi)容,所以不論你的server所在的操作系統(tǒng)是Linux還是Windows,也不論你的server是Apache還是Nginx,這些變量的名稱和含義都是一樣的。實(shí)際就是Apache/Nginx在將這些內(nèi)容填充到環(huán)境變量中,而具體填充規(guī)范則來自于CGI接口協(xié)議。
在C語言標(biāo)準(zhǔn)中有獲取環(huán)境變量值得庫函數(shù)——getenv。(頭文件stdlib.h)
[cpp] view plain copy
//比如
chr* str = NULL;
str = getenv("QUERY_STRING");
對(duì)于get請求,可以從環(huán)境變量QUERY_STRING中取出字符串 username=jelly&password=123456。然后程序自己做字符串的解析操作,解析出參數(shù)的key和value。而對(duì)于post請求,則是直接通過標(biāo)注輸入(STDIN)來獲取這個(gè)參數(shù)字符串,比如使用scanf或cin都可以。
在解析了請求、進(jìn)行了相應(yīng)的邏輯處理之后(比如檢查用戶名密碼是否一致),CGI程序要向前端頁面返回內(nèi)容,這是通過標(biāo)準(zhǔn)輸出(STDOUT)完成的,比如printf或cout,你可以返回xml,json,plain text或一個(gè)html網(wǎng)頁等等。這一步完成的是就是HTTP的響應(yīng)過程。所以在返回直接的數(shù)據(jù)之前,要先輸出HTTP協(xié)議的首部。比如,假設(shè)你想返回一個(gè)html網(wǎng)頁,那么你首先要輸出:
[cpp] view plain copy
cout<<"Content-Type:text/html\n\n"<<endl;
WARNNING:這里要注意,一定要輸出兩個(gè)換行符(\n)。因?yàn)镠TTP協(xié)議的首部和消息實(shí)體(如HTML代碼)之間用空行分割。
后面直接cout出html代碼(比如輸出你剛才輸入的用戶名成功登陸)。前端頁面就會(huì)收到這些html代碼,然后瀏覽器就渲染成網(wǎng)頁啦。這就是一次CGI完成的動(dòng)態(tài)網(wǎng)頁操作了。
Cgicc庫
進(jìn)行C++的CGI編程,需要手動(dòng)進(jìn)行字符串的解析處理,還有自行管理首部。比如資源轉(zhuǎn)移了,要返回302,并且在首部用Location給出新地址。很顯然,這些東西對(duì)于PHP、Python等語言都有內(nèi)置的解決方案。對(duì)于C++就需要第三方庫了。這里推薦一個(gè)GNU的開源庫——Cgicc。可以滿足常用的各類需求,除了解析get/post請求外,還能重定向,還可以設(shè)置Cookie,還可以上傳文件等等等等。
美中不足的就是Cgicc庫不支持SESSION。但是這個(gè)問題不大,我們可以很容易使用Cookie來實(shí)現(xiàn)SESSION功能。由于CGI本身是請求一次就創(chuàng)建一個(gè)進(jìn)程,返回之后進(jìn)程就結(jié)束(下文的FastCGI除外)。這時(shí)要在服務(wù)端維持一個(gè)SESSION的變量可選的解決方案是:用文件存儲(chǔ)或者在Redis、Memcached等內(nèi)存數(shù)據(jù)庫中存儲(chǔ)。而發(fā)給客戶端的SESSIONID就用Cgicc已經(jīng)支持的Cookie功能來完成,就可以了。
CGI的痛點(diǎn)與FastCGI
CGI是一種標(biāo)準(zhǔn),并不限定語言。所以Java、PHP、Python都可以通過這種方式來生成動(dòng)態(tài)網(wǎng)頁。但是實(shí)際上這些動(dòng)態(tài)語言卻很少這樣用。原來是CGI有一大硬傷。那就是每次CGI請求,那么Apache都有啟動(dòng)一個(gè)進(jìn)程去執(zhí)行這個(gè)CGI程序,即頗具Unix特色的fork-and-execute。當(dāng)用戶請求量大的時(shí)候,這個(gè)fork-and-execute的操作會(huì)嚴(yán)重拖慢Server的進(jìn)程。而Java的Servlet技術(shù)則是一種常駐內(nèi)存的技術(shù),不會(huì)頻繁的發(fā)生進(jìn)程上下文的創(chuàng)建和銷毀操作。
時(shí)勢造英雄,F(xiàn)astCGI技術(shù)應(yīng)運(yùn)而生。簡單來說,其本質(zhì)就是一個(gè)常駐內(nèi)存的進(jìn)程池技術(shù),由調(diào)度器負(fù)責(zé)將傳遞過來的CGI請求發(fā)送給處理CGI的handler進(jìn)程來處理。在一個(gè)請求處理完成之后,該處理進(jìn)程不銷毀,繼續(xù)等待下一個(gè)請求的到來。FCGI技術(shù)一出,CGI又一定程度上煥發(fā)了第二春。PHP-FPM本身是使PHP支持FCGI技術(shù)的一個(gè)Patch,現(xiàn)在已經(jīng)被納入PHP標(biāo)準(zhǔn)。當(dāng)然,支持C++的FCGI技術(shù)也出現(xiàn)了,Apache有FCGI的模塊可以安裝,比如mod_fcgid。
現(xiàn)代CGI的編程范式
前面我們知道,CGI可以直接返回一個(gè)html網(wǎng)頁。CGI程序本身也可以進(jìn)行各種計(jì)算、邏輯處理任務(wù)。隨著各類web前后端技術(shù)的發(fā)展,以及大數(shù)據(jù)、高并發(fā)的Server使用場景越來越多?,F(xiàn)代的CGI的用法,在發(fā)生變化。
現(xiàn)在,越來越多的任務(wù)從后端轉(zhuǎn)移到前端,前端頁面利用豐富的Js技術(shù)來進(jìn)行更多的處理。
JS可以使用Ajax技術(shù)來向后臺(tái)CGI發(fā)起數(shù)據(jù)請求。Ajax完成的是不需要刷新整個(gè)頁面就可以加載后端數(shù)據(jù)(比如從數(shù)據(jù)庫中取出)。
CGI一般不再用于直接返回html頁面,同時(shí)將復(fù)雜的計(jì)算、IO任務(wù)下沉到后端(后端可以進(jìn)一步進(jìn)行路由轉(zhuǎn)發(fā),實(shí)現(xiàn)負(fù)載均衡)。使CGI作為前后端之間的中間層。彼時(shí)CGI的職能是完成基本的數(shù)據(jù)交換:解析前端數(shù)據(jù)請求,再轉(zhuǎn)發(fā)給對(duì)應(yīng)后端;然后從后端取回?cái)?shù)據(jù),給前端返回XML或JSON。
前端JS利用XML/JSON中的數(shù)據(jù)來進(jìn)行填充,繪制出豐富的頁面。
上一篇CGI程序中POST和GET消息的處理
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
post和get的區(qū)別
史上最詳細(xì)的抓包教程 看到就是賺到
前后端分離與不分離的本質(zhì)區(qū)別!
web的應(yīng)用模式
提高ASP程序執(zhí)行效率的技巧
Apache與Tomcat 區(qū)別聯(lián)系
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服