linux網(wǎng)絡(luò)編程使用事件驅(qū)動(dòng)模型實(shí)現(xiàn)高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序_第1頁
linux網(wǎng)絡(luò)編程使用事件驅(qū)動(dòng)模型實(shí)現(xiàn)高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序_第2頁
linux網(wǎng)絡(luò)編程使用事件驅(qū)動(dòng)模型實(shí)現(xiàn)高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序_第3頁
linux網(wǎng)絡(luò)編程使用事件驅(qū)動(dòng)模型實(shí)現(xiàn)高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序_第4頁
linux網(wǎng)絡(luò)編程使用事件驅(qū)動(dòng)模型實(shí)現(xiàn)高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

使用大事驅(qū)動(dòng)模型實(shí)現(xiàn)高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序幾種網(wǎng)絡(luò)服務(wù)器模型的介紹與比較HYPERLINK"http://www.ibm.com/developerworks/cn/linux/l—cn—edntwk/"顧鋒磊,軟件工程師,IBM簡(jiǎn)介:

圍繞如何構(gòu)建一個(gè)高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序,本文從一個(gè)最簡(jiǎn)潔的服務(wù)器模型開頭,依次介紹了使用多線程的服務(wù)器模型、使用非堵塞接口的服務(wù)器模型、利用select()接口實(shí)現(xiàn)的基于大事驅(qū)動(dòng)的服務(wù)器模型,和使用libev大事驅(qū)動(dòng)庫的服務(wù)器模型.通過比較各個(gè)模型,得出大事驅(qū)動(dòng)模型更適合構(gòu)建高效穩(wěn)定的網(wǎng)絡(luò)服務(wù)器程序的結(jié)論。發(fā)布日期:

2010年10月14日

?前言大事驅(qū)動(dòng)為寬闊的程序員所熟識(shí),其最為人津津樂道的是在圖形化界面編程中的應(yīng)用;事實(shí)上,在網(wǎng)絡(luò)編程中大事驅(qū)動(dòng)也被廣泛使用,并大規(guī)模部署在高連接數(shù)高吞吐量的服務(wù)器程序中,如http服務(wù)器程序、ftp服務(wù)器程序等.相比于傳統(tǒng)的網(wǎng)絡(luò)編程方式,大事驅(qū)動(dòng)能夠極大的降低資源占用,增大服務(wù)接待能力,并提高網(wǎng)絡(luò)傳輸效率。關(guān)于本文提及的服務(wù)器模型,搜尋網(wǎng)絡(luò)可以查閱到很多的實(shí)現(xiàn)代碼,所以,本文將不拘泥于源代碼的陳設(shè)與分析,而側(cè)重模型的介紹和比較.使用libev大事驅(qū)動(dòng)庫的服務(wù)器模型將給出實(shí)現(xiàn)代碼。本文涉及到線程/時(shí)間圖例,只為表明線程在各個(gè)IO上確實(shí)存在堵塞時(shí)延,但并不保證時(shí)延比例的正確性和IO執(zhí)行先后的正確性;另外,本文所提及到的接口也只是筆者熟識(shí)的Unix/Linux接口,并未推舉Windows接口,讀者可以自行查閱對(duì)應(yīng)的Windows接口。HYPERLINK"http://www。ibm。com/developerworks/cn/linux/l-cn-edntwk/"\l"ibm-pcon”回頁首堵塞型的網(wǎng)絡(luò)編程接口幾乎全部的程序員第一次接觸到的網(wǎng)絡(luò)編程都是從listen()、send()、recv()等接口開頭的.使用這些接口可以很便利的構(gòu)建服務(wù)器/客戶機(jī)的模型。我們假設(shè)盼望建立一個(gè)簡(jiǎn)潔的服務(wù)器程序,實(shí)現(xiàn)向單個(gè)客戶機(jī)供應(yīng)類似于“一問一答”的內(nèi)容服務(wù)。

圖1。簡(jiǎn)潔的一問一答的服務(wù)器/客戶機(jī)模型?

我們注意到,大部分的socket接口都是堵塞型的.所謂堵塞型接口是指系統(tǒng)調(diào)用(一般是IO接口)不返回調(diào)用結(jié)果并讓當(dāng)前線程始終堵塞,只有當(dāng)該系統(tǒng)調(diào)用獲得結(jié)果或者超時(shí)出錯(cuò)時(shí)才返回。實(shí)際上,除非格外指定,幾乎全部的IO接口(包括socket接口)都是堵塞型的。這給網(wǎng)絡(luò)編程帶來了一個(gè)很大的問題,如在調(diào)用send()的同時(shí),線程將被堵塞,在此期間,線程將無法執(zhí)行任何運(yùn)算或響應(yīng)任何的網(wǎng)絡(luò)懇求.這給多客戶機(jī)、多業(yè)務(wù)規(guī)律的網(wǎng)絡(luò)編程帶來了挑戰(zhàn)。這時(shí),很多程序員可能會(huì)選擇多線程的方式來解決這個(gè)問題。多線程的服務(wù)器程序應(yīng)對(duì)多客戶機(jī)的網(wǎng)絡(luò)應(yīng)用,最簡(jiǎn)潔的解決方式是在服務(wù)器端使用多線程(或多進(jìn)程)。多線程(或多進(jìn)程)的目的是讓每個(gè)連接都擁有獨(dú)立的線程(或進(jìn)程),這樣任何一個(gè)連接的堵塞都不會(huì)影響其他的連接。簡(jiǎn)略使用多進(jìn)程還是多線程,并沒有一個(gè)特定的模式。傳統(tǒng)意義上,進(jìn)程的開銷要遠(yuǎn)遠(yuǎn)大于線程,所以,如果需要同時(shí)為較多的客戶機(jī)供應(yīng)服務(wù),則不推舉使用多進(jìn)程;如果單個(gè)服務(wù)執(zhí)行體需要消耗較多的CPU資源,譬如需要進(jìn)行大規(guī)?;蜷L(zhǎng)時(shí)間的數(shù)據(jù)運(yùn)算或文件訪問,則進(jìn)程較為平安。通常,使用pthread_create()創(chuàng)建新線程,fork()創(chuàng)建新進(jìn)程.我們假設(shè)對(duì)上述的服務(wù)器/客戶機(jī)模型,提出更高的要求,即讓服務(wù)器同時(shí)為多個(gè)客戶機(jī)供應(yīng)一問一答的服務(wù)。于是有了如下的模型.?圖2。多線程的服務(wù)器模型?

在上述的線程/時(shí)間圖例中,主線程持續(xù)等待客戶端的連接懇求,如果有連接,則創(chuàng)建新線程,并在新線程中供應(yīng)為前例同樣的問答服務(wù)。很多初學(xué)者可能不明白為何一個(gè)socket可以accept多次。實(shí)際上,socket的設(shè)計(jì)者可能特意為多客戶機(jī)的情況留下了伏筆,讓accept()能夠返回一個(gè)新的socket.下面是accept接口的原型:?intaccept(ints,structsockaddr*addr,socklen_t*addrlen);輸入?yún)?shù)s是從socket(),bind()和listen()中沿用下來的socket句柄值。執(zhí)行完bind()和listen()后,操作系統(tǒng)已經(jīng)開頭在指定的端口處監(jiān)聽全部的連接懇求,如果有懇求,則將該連接懇求加入懇求隊(duì)列。調(diào)用accept()接口正是從sockets的懇求隊(duì)列抽取第一個(gè)連接信息,創(chuàng)建一個(gè)與s同類的新的socket返回句柄。新的socket句柄即是后續(xù)read()和recv()的輸入?yún)?shù)。如果懇求隊(duì)列當(dāng)前沒有懇求,則accept()將進(jìn)入堵塞狀態(tài)直到有懇求進(jìn)入隊(duì)列。上述多線程的服務(wù)器模型似乎完善的解決了為多個(gè)客戶機(jī)供應(yīng)問答服務(wù)的要求,但其實(shí)并不盡然。如果要同時(shí)響應(yīng)成百上千路的連接懇求,則無論多線程還是多進(jìn)程都會(huì)嚴(yán)重占據(jù)系統(tǒng)資源,降低系統(tǒng)對(duì)外界響應(yīng)效率,而線程與進(jìn)程本身也更容易進(jìn)入假死狀態(tài)。很多程序員可能會(huì)考慮使用“線程池”或“連接池”?!熬€程池”旨在削減創(chuàng)建和銷毀線程的頻率,其維持肯定合理數(shù)量的線程,并讓空閑的線程重新?lián)?dāng)新的執(zhí)行任務(wù)?!斑B接池”維持連接的緩存池,盡量重用已有的連接、削減創(chuàng)建和關(guān)閉連接的頻率。這兩種技術(shù)都可以很好的降低系統(tǒng)開銷,都被廣泛應(yīng)用很多大型系統(tǒng),如websphere、tomcat和各種數(shù)據(jù)庫等。但是,“線程池”和“連接池"技術(shù)也只是在肯定程度上緩解了頻繁調(diào)用IO接口帶來的資源占用。而且,所謂“池”始終有其上限,當(dāng)懇求大大超過上限時(shí),“池”構(gòu)成的系統(tǒng)對(duì)外界的響應(yīng)并不比沒有池的時(shí)候效果好多少。所以使用“池"必須考慮其面臨的響應(yīng)規(guī)模,并依據(jù)響應(yīng)規(guī)模調(diào)整“池”的大小。對(duì)應(yīng)上例中的所面臨的可能同時(shí)消滅的上千甚至上萬次的客戶端懇求,“線程池”或“連接池”或許可以緩解部分壓力,但是不能解決全部問題。總之,多線程模型可以便利高效的解決小規(guī)模的服務(wù)懇求,但面對(duì)大規(guī)模的服務(wù)懇求,多線程模型并不是最佳方案。下一章我們將商量用非堵塞接口來嘗試解決這個(gè)問題。HYPERLINK”http://www.ib/developerworks/cn/linux/l—cn—edntwk/”\l”ibm—pcon"回頁首非堵塞的服務(wù)器程序以上面臨的很多問題,肯定程度是IO接口的堵塞特性導(dǎo)致的.多線程是一個(gè)解決方案,還一個(gè)方案就是使用非堵塞的接口。非堵塞的接口相比于堵塞型接口的顯著差異在于,在被調(diào)用之后立即返回。使用如下的函數(shù)可以將某句柄fd設(shè)為非堵塞狀態(tài).?fcntl(fd,F_SETFL,O_NONBLOCK);下面將給出只用一個(gè)線程,但能夠同時(shí)從多個(gè)連接中檢測(cè)數(shù)據(jù)是否送達(dá),并且接受數(shù)據(jù)。

圖3.使用非堵塞的接收數(shù)據(jù)模型?

在非堵塞狀態(tài)下,recv()接口在被調(diào)用后立即返回,返回值代表了不同的含義。如在本例中,recv()返回值大于0,表示接受數(shù)據(jù)完畢,返回值即是接受到的字節(jié)數(shù);recv()返回0,表示連接已經(jīng)正常斷開;recv()返回-1,且errno等于EAGAIN,表示recv操作還沒執(zhí)行完成;recv()返回—1,且errno不等于EAGAIN,表示recv操作遇到系統(tǒng)錯(cuò)誤errno??梢钥吹椒?wù)器線程可以通過循環(huán)調(diào)用recv()接口,可以在單個(gè)線程內(nèi)實(shí)現(xiàn)對(duì)全部連接的數(shù)據(jù)接收工作。但是上述模型絕不被推舉。由于,循環(huán)調(diào)用recv()將大幅度推高CPU占用率;此外,在這個(gè)方案中,recv()更多的是起到檢測(cè)“操作是否完成"的作用,實(shí)際操作系統(tǒng)供應(yīng)了更為高效的檢測(cè)“操作是否完成“作用的接口,例如select().HYPERLINK”http://www。ibm.com/developerworks/cn/linux/l-cn-edntwk/”\l"ibm-pcon"回頁首使用select()接口的基于大事驅(qū)動(dòng)的服務(wù)器模型大部分Unix/Linux都支持select函數(shù),該函數(shù)用于探測(cè)多個(gè)文件句柄的狀態(tài)變化.下面給出select接口的原型:FD_ZERO(intfd,fd_set*fds)FD_SET(intfd,fd_set*fds)FD_ISSET(intfd,fd_set*fds)FD_CLR(intfd,fd_set*fds)intselect(intnfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtimeval*timeout)這里,fd_set類型可以簡(jiǎn)潔的理解為按bit位標(biāo)記句柄的隊(duì)列,例如要在某fd_set中標(biāo)記一個(gè)值為16的句柄,則該fd_set的第16個(gè)bit位被標(biāo)記為1。簡(jiǎn)略的置位、驗(yàn)證可使用FD_SET、FD_ISSET等宏實(shí)現(xiàn)。在select()函數(shù)中,readfds、writefds和exceptfds同時(shí)作為輸入?yún)?shù)和輸出參數(shù)。如果輸入的readfds標(biāo)記了16號(hào)句柄,則select()將檢測(cè)16號(hào)句柄是否可讀。在select()返回后,可以通過檢查readfds有否標(biāo)記16號(hào)句柄,來推斷該“可讀”大事是否發(fā)生。另外,用戶可以設(shè)置timeout時(shí)間.下面將重新模擬上例中從多個(gè)客戶端接收數(shù)據(jù)的模型。

圖4.使用select()的接收數(shù)據(jù)模型

上述模型只是描述了使用select()接口同時(shí)從多個(gè)客戶端接收數(shù)據(jù)的過程;由于select()接口可以同時(shí)對(duì)多個(gè)句柄進(jìn)行讀狀態(tài)、寫狀態(tài)和錯(cuò)誤狀態(tài)的探測(cè),所以可以很容易構(gòu)建為多個(gè)客戶端供應(yīng)獨(dú)立問答服務(wù)的服務(wù)器系統(tǒng)。?圖5.使用select()接口的基于大事驅(qū)動(dòng)的服務(wù)器模型?

這里需要指出的是,客戶端的一個(gè)connect()操作,將在服務(wù)器端激發(fā)一個(gè)“可讀大事",所以select()也能探測(cè)來自客戶端的connect()行為。上述模型中,最關(guān)鍵的地方是如何動(dòng)態(tài)維護(hù)select()的三個(gè)參數(shù)readfds、writefds和exceptfds。作為輸入?yún)?shù),readfds應(yīng)該標(biāo)記全部的需要探測(cè)的“可讀大事"的句柄,其中永久包括那個(gè)探測(cè)connect()的那個(gè)“母”句柄;同時(shí),writefds和exceptfds應(yīng)該標(biāo)記全部需要探測(cè)的“可寫大事”和“錯(cuò)誤大事”的句柄(使用FD_SET()標(biāo)記)。作為輸出參數(shù),readfds、writefds和exceptfds中的保存了select()捕獲到的全部大事的句柄值.程序員需要檢查的全部的標(biāo)記位(使用FD_ISSET()檢查),以確定到底哪些句柄發(fā)生了大事.上述模型主要模擬的是“一問一答”的服務(wù)流程,所以,如果select()發(fā)現(xiàn)某句柄捕獲到了“可讀大事”,服務(wù)器程序應(yīng)準(zhǔn)時(shí)做recv()操作,并依據(jù)接收到的數(shù)據(jù)籌備好待發(fā)送數(shù)據(jù),并將對(duì)應(yīng)的句柄值加入writefds,籌備下一次的“可寫大事”的select()探測(cè)。同樣,如果select()發(fā)現(xiàn)某句柄捕獲到“可寫大事”,則程序應(yīng)準(zhǔn)時(shí)做send()操作,并籌備好下一次的“可讀大事”探測(cè)籌備。下圖描述的是上述模型中的一個(gè)執(zhí)行周期。?圖6.一個(gè)執(zhí)行周期?

這種模型的特征在于每一個(gè)執(zhí)行周期都會(huì)探測(cè)一次或一組大事,一個(gè)特定的大事會(huì)觸發(fā)某個(gè)特定的響應(yīng)。我們可以將這種模型歸類為“大事驅(qū)動(dòng)模型"。相比其他模型,使用select()的大事驅(qū)動(dòng)模型只用單線程(進(jìn)程)執(zhí)行,占用資源少,不消耗太多CPU,同時(shí)能夠?yàn)槎嗫蛻舳斯?yīng)服務(wù)。如果試圖建立一個(gè)簡(jiǎn)潔的大事驅(qū)動(dòng)的服務(wù)器程序,這個(gè)模型有肯定的參考價(jià)值。但這個(gè)模型照舊有著很多問題。首先,select()接口并不是實(shí)現(xiàn)“大事驅(qū)動(dòng)”的最好選擇.由于當(dāng)需要探測(cè)的句柄值較大時(shí),select()接口本身需要消耗大量時(shí)間去輪詢各個(gè)句柄。很多操作系統(tǒng)供應(yīng)了更為高效的接口,如linux供應(yīng)了epoll,BSD供應(yīng)了kqueue,Solaris供應(yīng)了/dev/poll…。如果需要實(shí)現(xiàn)更高效的服務(wù)器程序,類似epoll這樣的接口更被推舉。圓滿的是不同的操作系統(tǒng)特供的epoll接口有很大差異,所以使用類似于epoll的接口實(shí)現(xiàn)具有較好跨平臺(tái)能力的服務(wù)器會(huì)比較困難.其次,該模型將大事探測(cè)和大事響應(yīng)夾雜在一起,一旦大事響應(yīng)的執(zhí)行體浩大,則對(duì)整個(gè)模型是災(zāi)難性的。如下例,浩大的執(zhí)行體1的將直接導(dǎo)致響應(yīng)大事2的執(zhí)行體遲遲得不到執(zhí)行,并在很大程度上降低了大事探測(cè)的準(zhǔn)時(shí)性.?圖7.浩大的執(zhí)行體對(duì)使用select()的大事驅(qū)動(dòng)模型的影響?

幸運(yùn)的是,有很多高效的大事驅(qū)動(dòng)庫可以屏蔽上述的困難,常見的大事驅(qū)動(dòng)庫有libevent庫,還有作為libevent替代者的libev庫。這些庫會(huì)依據(jù)操作系統(tǒng)的特點(diǎn)選擇最合適的大事探測(cè)接口,并且加入了信號(hào)(signal)等技術(shù)以支持異步響應(yīng),這使得這些庫成為構(gòu)建大事驅(qū)動(dòng)模型的不二選擇。下章將介紹如何使用libev庫替換select或epoll接口,實(shí)現(xiàn)高效穩(wěn)定的服務(wù)器模型.HYPERLINK”http://www。ibm。com/developerworks/cn/linux/l-cn-edntwk/"\l"ibm-pcon"回頁首使用大事驅(qū)動(dòng)庫libev的服務(wù)器模型Libev是一種高性能大事循環(huán)/大事驅(qū)動(dòng)庫。作為libevent的替代作品,其第一個(gè)版本發(fā)布與2007年11月。Libev的設(shè)計(jì)者聲稱libev擁有更快的速度,更小的體積,更多功能等優(yōu)勢(shì),這些優(yōu)勢(shì)在很多測(cè)評(píng)中得到了證明.正由于其良好的性能,很多系統(tǒng)開頭使用libev庫。本章將介紹如何使用Libev實(shí)現(xiàn)供應(yīng)問答服務(wù)的服務(wù)器。(事實(shí)上,現(xiàn)存的大事循環(huán)/大事驅(qū)動(dòng)庫有很多,作者也無意推舉讀者肯定使用libev庫,而只是為了說明大事驅(qū)動(dòng)模型給網(wǎng)絡(luò)服務(wù)器編程帶來的便利和好處。大部分的大事驅(qū)動(dòng)庫都有著與libev庫相類似的接口,只要明白大致的原理,即可靈敏選擇合適的庫。)與前章的模型類似,libev同樣需要循環(huán)探測(cè)大事是否產(chǎn)生。Libev的循環(huán)體用ev_loop結(jié)構(gòu)來表達(dá),并用ev_loop()來啟動(dòng)。?voidev_loop(ev_loop*loop,intflags)Libev支持八種大事類型,其中包括IO大事.一個(gè)IO大事用ev_io來表征,并用ev_io_init()函數(shù)來初始化:?voidev_io_init(ev_io*io,callback,intfd,intevents)初始化內(nèi)容包括回調(diào)函數(shù)callback,被探測(cè)的句柄fd和需要探測(cè)的大事,EV_READ表“可讀大事”,EV_WR(shí)ITE表“可寫大事”?,F(xiàn)在,用戶需要做的僅僅是在合適的時(shí)候,將某些ev_io從ev_loop加入或剔除.一旦加入,下個(gè)循環(huán)即會(huì)檢查ev_io所指定的大事有否發(fā)生;如果該大事被探測(cè)到,則ev_loop會(huì)自動(dòng)執(zhí)行ev_io的回調(diào)函數(shù)callback();如果ev_io被注銷,則不再檢測(cè)對(duì)應(yīng)大事。無論某ev_loop啟動(dòng)與否,都可以對(duì)其添加或刪除一個(gè)或多個(gè)ev_io,添加刪除的接口是ev_io_start()和ev_io_stop()。?voidev_io_start(ev_loop*loop,ev_io*io)?voidev_io_stop(EV_A_*)由此,我們可以容易得出如下的“一問一答"的服務(wù)器模型.由于沒有考慮服務(wù)器端主動(dòng)終止連接機(jī)制,所以各個(gè)連接可以維持任意時(shí)間,客戶端可以自由選擇退出時(shí)機(jī)。?圖8.使用libev庫的服務(wù)器模型

上述模型可以接受任意多個(gè)連接,且為各個(gè)連接供應(yīng)完全獨(dú)立的問答服務(wù)。借助libev供應(yīng)的大事循環(huán)/大事驅(qū)動(dòng)接口,上述模型有機(jī)會(huì)具備其他模型不能供應(yīng)的高效率、低資源占用、穩(wěn)定性好和編寫簡(jiǎn)潔等特點(diǎn)。由于傳統(tǒng)的web服務(wù)器,ftp服務(wù)器及其他網(wǎng)絡(luò)應(yīng)用程序都具有“一問一答"的通訊規(guī)律,所以上述使用libev庫的“一問一答”模型對(duì)構(gòu)建類似的服務(wù)器程序具有參考價(jià)值;另外,對(duì)于需要實(shí)現(xiàn)遠(yuǎn)程監(jiān)視或遠(yuǎn)程遙控的應(yīng)用程序,上述模型同樣供應(yīng)了一個(gè)可行的實(shí)現(xiàn)方案。HYPERLINK"http://www.ibm.com/developerworks/cn/linux/l-cn-edntwk/"\l”ibm-pcon"回頁首總結(jié)本文圍繞如何構(gòu)建一個(gè)供應(yīng)“一問一答”的服務(wù)器程序,先后商量了用堵塞型的socket接口實(shí)現(xiàn)的模型,使用多線程的模型,使用select()接口的基于大事驅(qū)動(dòng)的服務(wù)器模型,直到使用libev大事驅(qū)動(dòng)庫的服務(wù)器模型.文章對(duì)各種模型的優(yōu)缺點(diǎn)都做了比較,從比較中得出結(jié)論,即使用“大事驅(qū)動(dòng)模型"可以的實(shí)現(xiàn)更為高效穩(wěn)定的服務(wù)器程序.文中描述的多種模型可以為讀者的網(wǎng)絡(luò)編程供應(yīng)參考價(jià)值.參考資料學(xué)習(xí)HYPERLINK”http://software.schmorp.de/pkg/libev.html"libev官網(wǎng)供應(yīng)了libev的源碼和文檔.HYPERLINK"http://monkey。org/~provos/libevent/"libevent官網(wǎng)供應(yīng)了libevent的源碼和文檔?!禪NIX環(huán)境高級(jí)編程》,作者W。RichardStevens&StephenA。Rago。在

HYPERL

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論