




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第1章分布式計算概論提綱1.1 分布式計算概念1.2 分布式計算模式1.3 分布式基礎問題與理論1.4 經典分布式(計算)系統分布式計算的定義分布式計算是一門計算機科學,主要研究對象是分布式系統。在介紹分布式計算概念前,首先簡單了解一下什么是分布式系統。簡單地說,一個分布式系統是由若干通過網絡互聯的計算機組成的軟硬件系統[1],且這些計算機互相配合以完成一個共同的目標(往往這個共同的目標稱為“項目”)分布式計算指在分布式系統上執行的計算。分布式計算是將一個大型計算任務分成很多部分分別交給其他的計算機處理,并將所有的計算結果合并為原問題的解決方案。這里與并行計算不同的是,并行計算是使用多個處理器并行執行單個計算。分布式計算的優缺點優點
高可伸縮性
資源共享
高性價比
容錯性
超大規模
通用性弱點
多點故障一臺或多臺計算機的故障,或一條或多條網絡鏈路的故障,都會導致分布式系統出現問題
安全性低分布式系統為非授權用戶的攻擊提供了更多機會
大規模資源調度的復雜性資源調度通常是一個NP-hard問題,大規模資源調度往往具有很高的復雜性和不確定性提綱1.1 分布式計算概念1.2 分布式計算模式1.3 分布式基礎問題與理論1.4 經典分布式(計算)系統分布式云計算相關計算形式分布式云計算相關計算形式分布式云計算相關計算形式當前最熱門計算機技術對比分布式云計算相關計算形式當前最熱門計算機技術對比集中計算與分布式計算串行運算與并行運算并行運算與分布式計算的區別:分布式計算強調的是任務的分布執行,而并行計算強調的是任務的并發執行云計算概念提出提出者:Google工程師,比希利亞,27歲出發點:推廣Google超級強大的計算資源,招賢納士結果:蜂擁而至,名噪一時,被視為“云”的起源*-12-云計算分類私有云公有云混合云操作系統+應用服務引擎應用系統基礎設施(IaaS)應用平臺(PaaS)應用軟件(SaaS)InfrastructureasaService以服務的形式提供虛擬硬件資源,如虛擬主機/存儲/網絡/數據庫管理等資源。用于無需購買服務器、網絡設備、存儲設備,只需通過互聯網租賃即可搭建自己的應用系統典型應用:AmazonWeb
Service(AWS)PlatformasaService提供應用服務引擎,如互聯網應用編程接口/運行平臺等。用戶基于該應用服務引擎,可以構建該類應用。典型應用:GoogleAppEngine,F,MicrosoftAzure服務平臺SoftwareasaService用戶通過Internet(如瀏覽器)來使用軟件。用戶不必購買軟件,只需按需租用軟件典型應用:GoogleDoc,S,OracleCRMOnDemand,OfficeLiveWorkspace面向外部用戶需求,通過開放網絡提供云計算服務IDC,GoogleApp,Saleforce在線CRM按提供的服務類型按云服務的對象大型企業按照云計算的架構搭建平臺,面向企業內部需求提供云計算服務企業內部數據中心等兼顧以上兩種情況的云計算服務AmazonWebServer等既為企業內部又為外部用戶提供云計算服務云計算與網格計算網格計算:利用互聯網把地理上廣泛分布的各種資源(計算、存儲、帶寬、軟件、數據、信息、知識等)連成一個邏輯整體,就像一臺超級計算機一樣,為用戶提供一體化信息和應用服務(計算、存儲、訪問等)。網格計算強調資源共享,任何節點都可以請求使用其它節點的資源,任何節點都需要貢獻一定資源給其他節點。云計算強調專有,請求或獲取的資源是專有的,并且由少數團體提供,使用者不需要貢獻自己的資源。網格計算側重并行的計算集中性需求,并且難以自動擴展。云計算側重事務性應用,大量的單獨的請求,可以實現自動或半自動的擴展。云計算包含的網格計算特征:(1)提供在線的計算、存儲等服務(2)超大規模的資源組合(3)資源的虛擬化*14云計算與分布式計算分布式計算(狹義):將待解決問題分成多個小問題,再分配給許多計算系統處理,最后將處理結果加以綜合。特點:把計算任務分派給網絡中的多臺獨立的機器優點稀有資源可以共享通過分布式計算可以在多臺計算機上平衡計算負載可以把程序放在最適合運行它的計算機上流行的分布式項目SETI@Home:尋找外星文明RC-72:密碼分析破解,研究和尋找最為安全的密碼系統Folding@home:研究蛋白質折疊、聚合問題UnitedDevices:尋找對抗癌癥的有效的藥物GIMPS:尋找最大的梅森素數(解決較為復雜的數學問題)云計算包含的分布式計算特征:1)通過資源調度和組合滿足用戶的資源請求;2)對外提供統一的、單一的接口云計算是分布式計算的發展,是分布式計算的一種新形式。分布式郵箱系統15云計算與并行計算并行計算:是相對于串行計算的概念,最早出現于上個世紀六七十年代,指在并行計算機上所做的計算。現通常指同時使用多種計算資源解決計算問題的過程,即一個程序的多個部分同時運行于多個處理器上。分類:可分為時間上的并行(流水線)和空間上的并行(多處理器并發)并行計算問題的特征將工作分離成離散部分,有助于同時解決隨時并及時地執行多個程序指令(多條線同時運行)多計算資源下解決問題的耗時要少于單個計算資源下的耗時云計算包含的并行計算特征:用戶資源(單一類型和組合類型)請求的同時處理*16云計算與對等計算對等計算系統中,每個節點都擁有對等的功能與責任,既可以充當服務器向其他節點提供數據或服務,又可以作為客戶機享用其他節點提的供數據或服務,節點之間的交互可以是直接對等的,任何節點可以隨時自由地加入或離開系統。對等計算:有可能作為云計算的一個類型預測:將可能以“對等子云”的形式出現在云計算中。依據:云計算對超大規模、多類型資源的統一管理是困難的;對等計算具有魯棒性、可擴展性、成本、搜索等方面的優點Google的云計算服務曾出現嚴重問題,Gmail、Blogger和Spreadsheet等服務均長時間當機。亞馬遜S3云計算服務也曾出現問題。而P2P系統則有更強的抗毀能力。*17霧計算基本概念霧計算是個很形象的名稱,提出它的GinnyNichols提了一個有趣的說法“霧是接近地面的云”。這句話有兩層含義:1)霧計算和云計算有很多相似。例如:它們都基于虛擬化技術,從共享的資源池中為多用戶提供資源。2)“接近地面”。這也指出了霧和云的一個不同——網絡拓撲中的位置。霧的概念:霧節點所使用的設備:
霧主要使用邊緣網絡中的設備。這些設備可以是傳統網絡設備(早已部署在網絡中的路由器,交換機,網關等等),也可以是專門部署的本地服務器。霧計算基本原理霧計算概念示意圖霧計算實例智能交通燈系統霧計算的引入將為智能交通燈系統帶來更多的可能性。如:監控過程中,相鄰幀間畫面只有部分變化,非常適于在霧節點處緩存若干幀畫面,壓縮后再傳向中心機房,這樣從霧節點到機房的網絡帶寬將得到很大緩解。在霧節點處,可判斷監控畫面中是否有救護車頭燈閃爍,做出實時決策發送給對應交通燈,協助救護車通過。
邊緣計算基本概念邊緣計算(EdgeComputing)指的是接近于事物,數據和行動源頭處的計算也被稱為:鄰近計算或者接近計算(ProximityComputing)邊緣計算的概念:邊緣網絡:
邊緣計算讓數據在邊緣網絡處處理。邊緣網絡基本上由終端設備(例如移動手機、智能物品等等)、邊緣設備(例如邊界路由器、機頂盒、網橋、基站、無線接入點等等)、邊緣服務器等構成。邊緣計算基本原理云計算、霧計算、邊緣計算關系:霧計算也可以進行邊緣計算。除了邊緣網絡,霧計算也可以拓展到核心網絡。邊緣和核心網絡(例如核心路由器、區域服務器、廣域網路開關等等)的組件都可以作為霧計算基礎設施。邊緣計算依賴于不構成網絡的單獨節點,需要通過云實現孤島中節點的對等流量傳輸。霧計算用幾個層次形成網絡,節點之間具有廣泛的對等互連能力。霧計算以及邊緣計算都不是用來代替云計算,它們共同形成一個彼此受益的計算模型。邊緣計算實例智能交通燈系統無人駕駛汽車走向規模化應用必須存儲和運算海量的數據。無人駕駛汽車要在高速行駛過程中,通過無線網絡與云端進行大量超低時延、超大流量的數據交互,現有網絡根本沒有能力支撐。依靠移動邊緣計算,數據可以就近存儲于車輛附近位置甚至車身上。在車輛高速度運動過程中,位置信息變化十分迅速,被置于車身上的最末端的移動邊緣計算服務器能夠精確地實時感知車輛位置的變動,并將分析所得結果以極低延遲(通常是毫秒級)傳送給臨近區域內其他聯網車輛,以便車輛做出決策。
移動邊緣計算移動邊緣計算就是利用無線接入網絡就近提供電信用戶IT所需服務和云端計算功能,而創造出一個具備高性能、低延遲與高帶寬的電信級服務環境,加速網絡中各項內容、服務及應用的快速下載,讓消費者享有不間斷的高質量網絡體驗。移動邊緣計算把無線網絡和互聯網兩者技術有效融合在一起。移動云計算移動云計算是指通過移動網絡以按需、易擴展的方式獲得所需的基礎設施、平臺、軟件(或應用)等的一種IT資源或(信息)服務的交付與使用模式。如圖所示,移動云計算是云計算技術在移動互聯網中的應用,本質上就是基于移動終端獲取各種云端服務的技術。大數據計算概念隨著互聯網與計算機系統需要處理的數量越來越大,大數據計算成為一種非常重要的數據分析處理模式。大數據計算一般是指利用分布式計算技術對海量數據進行在線或離線的實時性或批處理分析計算。當前大數據計算的主要模式有:基于MapReduce的批處理計算、流式計算、基于Spark的內存計算。基于MapReduce的批處理計算InputsplitshuffleoutputMapReduce計算模式的主要思想是將自動分割要執行的問題(例如程序)拆解成Map和Reduce兩個函數操作,然后對分塊的大數據采用“分而治之”的并行處理方式分析計算數據。大數據流式計算大數據批處理計算關注數據處理的吞吐量,而大數據流式計算更關注數據處理的實時性。流式計算具有很強的實時性,需要對應用源源不斷產生的數據實時進行處理,使數據不積壓、不丟失,常用于處理電信、電力等行業應用以及互聯網行業的訪問日志等。基于Spark的內存計算由于MapReduce計算過程中需要讀寫HDFS存儲(訪問磁盤IO),而在Spark內存計算過程中,使用內存替代了使用HDFS存儲中間結果,即在進行大數據分析處理時使用分布式內存計算,內存訪問要比磁盤快得多。因此,基于Spark的內存計算的數據處理性能會提升很多,特別是針對需要多次迭代大數據計算的應用。無服務器計算無服務器計算來自英文ServerlessComputing的翻譯,簡稱為Serverless,它并不是指沒有服務器,而是說,對于用戶,服務器變得“不可見”了(或者說“無感知”),是指開發者不需要直接管理服務器資源。Serverless是一種云計算模型,它允許開發者編寫和部署功能單元(函數)而無需關心底層的服務器基礎設施。在Serverless架構中,云服務提供商負責動態管理和分配服務器資源,根據實際需要為函數執行提供計算資源。Serverless的核心目的,就是在云計算的基礎上,再向前邁進一步,徹底“包攬”所有的環境工作,直接提供計算服務。在Serverless架構下,開發者只需編寫代碼并上傳,云平臺就會自動準備好相應的計算資源,完成運算并輸出結果,從而大幅簡化開發運維過程。也就說,Serverless是云計算的進一步延伸,所以,它繼承了云計算的最大特點——按需彈性伸縮、按需付費。無服務器計算從層級上來看,Serverless在傳統云計算SaaS的Application(應用)層級之上,又加了一層——function(函數),如圖所示。它的顆粒度更細,可以更靈活地滿足用戶的算力需求。按照CNCF對Serverless的定義,Serverless架構是采用FaaS(函數即服務)和BaaS(后端服務)服務來解決問題的一種設計。即Serverless=FaaS+BaaS。FaaS就是Functionasaservice(函數即服務)。每一個函數都是一個服務,函數可以由任何語言編寫,直接托管在云平臺,以服務形式運行,通過事件觸發。提綱1.1 分布式計算概念1.2 分布式計算模式1.3 分布式基礎問題與理論1.4 經典分布式(計算)系統2000年7月,來自加州大學伯克利分校EricBrewer教授首次提出了著名的CAP猜想。2年后,來自麻省理工學院的SethGilbert和NancyLynch從理論上證明了Brewer教授CAP猜想。從此,CAP理論正式在學術上成為了分布式計算領域的公認定理,并深深地影響了分布式計算的發展。分布式系統的CAP理論:對于一個分布式計算系統來說,不可能同時滿足以下三點:一致性(C)、可用性(A)、分區容忍性(P)。一致性(C):即Consistency,所有節點訪問同一份最新的數據副本。在分布式系統中的所有數據備份,在同一時刻是否同樣的值。可用性(A):即Availability,對數據更新具備高可用性。在集群中一部分節點故障后,集群整體還能響應客戶端的讀寫請求。。分區容錯性(P):即Partitiontolerance,當分布式系統集群中的某些結點無法聯系時仍能正常提供服務。*33分布式系統的CAP定理CAP理論一個說明CAP理論的分布式應用例子1)正常情況:服務器N1和N2分別寫、讀數據,且服務器N1和N2通過同步消息來實現數據讀寫的一致性。2)當服務器N1和N2之間的通信異常中斷時:則系統(服務器N2)要么只能讀取舊數據,犧牲一致性;要么服務器N1的寫操作就會隨著數據更新消息發送失敗而回滾,系統無法使用,違背了可用性。提綱1.1 分布式計算概念1.2 分布式計算模式1.3 分布式基礎問題與理論1.4 經典分布式(計算)系統分布式系統介紹分布式系統:指通過網絡互連,可協作執行某個任務的獨立計算機集合。分布式系統介紹WWW(WorldWideWeb)是全球最大的分布式系統,互聯網服務之一統一資源標識符(URI)資源定位器(URL)超文本傳輸協議(HTML)客戶機/服務器(Client/Server)模式分布式系統介紹SETI@home(尋找外星人)搜尋證實地球外智能生物存在的證據志愿參加人數最多的分布式項目(Project)屏幕保護模式下的后臺運行(客戶端計算為主)1999-2005543萬用戶、243萬年累計計算沒有發現外星文明直接證據分布式系統介紹BOINC項目(BerkeleyOpenInfrastructureforNetworkComputing)傳統客戶端/服務器架構服務器端配置:數據庫服務器、數據處理服務器、資源任務調配服務器、Web服務器等子系統組成客戶端設置志愿計算功能服務器(軟件)用于:數學、物理、化學、生物科學、地理科學等項目計算最為流行的分布式計算平臺分布式系統介紹分布式系統介紹OpenStackOpenStack是一個開源的云計算管理平臺項目目標是提供實施簡單、可大規模擴展、豐富、標準統一的云計算管理平臺由一系列具有RESTful接口的Web服務所實現的,是一系列組件服務集合OpenStack本身是一個分布式系統,不但各個服務可以分布部署,服務中的組件也可以分布部署OpenStack包含了許多組件服務Nova:提供計算服務;Keystone:提供認證服務;Glance:提供鏡像服務;Neutron:提供網絡服務;Horizon:提供儀表盤服務;Swift:提供對象存儲服務;Cinder:提供塊存儲服務;Heat:提供編排服務;Ceilometer:提供計費和監控服務;Trove:提供數據庫服務;Sahara:提供數據處理服務分布式系統介紹OpenStackOpenStack的總體架構分布式系統介紹HadoopHadoop是一個由Apache基金會所開發的分布式系統基礎架構。起源于開源網絡搜索引擎ApacheNutch,基于谷歌分布式文件系統“GFS”和分布式數據處理系統“MapReduce”兩篇論文實現的開源版本包括核心的分布式文件存儲系統HDFS和分布式計算框架MapReduce,以及用于集群資源管理的YARN分布式系統介紹HadoopHDFS集群按照管理節點-工作節點模式運行,其中NameNode為管理節點,DataNode為工作節點,SecondaryNameNode是輔助namenode分布式系統介紹HadoopHBase是一個在HDFS上開發的面向列的分布式數據庫,服務依賴于Zookeeper,用一個Master節點協調管理一個或多個Regionserver從屬機分布式系統介紹HadoopYARN是Hadoop的集群資源管理系統,ResourceManager是一個全局的資源管理器ApplicationMaster是應用程序級別的管理器NodeManager是YARN中每個節點上的代理管理器分布式系統介紹Spark一種基于內存的快速、通用、可擴展的大數據分析計算引擎,相對于MapReduce的批處理計算,Spark可以帶來上百倍的性能提升其核心是建立在統一的抽象彈性分布式數據集(ResilienntDistributedDatasets,RDD)之上的,RDD允許開發人員在大型集群上執行基于內存的計算,同時屏蔽了Spark底層對數據的復雜抽象和處理Spark軟件棧包含四大組件:SparkSQL:SparkSQL是Spark中用于處理結構化數據的組件;SparkStreaming:SparkStreaming是Spark提供用于處理實時的流數據的組件;MLlib:MLlib是Spark中集成了常見的機器學習模型的組件GraphX:GraphX是Spark提供圖計算和并行圖計算功能的組件。分布式系統介紹Spark作為一個開源集群運算框架,Spark共支持四種集群運行模式:Standalone模式,基于ApahceMesos,基于HadoopYARN以及基于Kubernetes。ClusterManager:控制整個集群,監控worker;Worker節點:從節點,負責控制計算節點,啟動Executor或者Driver;Driver:運行Application;Executor:執行器。Spark運行架構圖如下。分布式系統介紹KubernetesGoogle開源的一個容器編排引擎,它支持自動化部署、大規模可伸縮、應用容器化管理。Kubernetes將集群中的機器劃分為一個Master節點和一群工作節點(Node)。其中Master組件提供集群的管理控制中心;Node組件提供Kubernetes運行時環境,以及維護Pod。分布式系統介紹其他分布式計算項目C(模擬全球氣象變化)Quake-CatcherNetwork(強力地震觀測預測網)WorldCommunityGrid(查詢人類疾病的治療方法)Einstein@Home(尋找脈沖星的引力波)FightAIDS@home(研究艾滋病生理原理和相關藥物)Folding@home(了解蛋白質折疊)GIMPS(尋找新的梅森素數)D(破解密鎖)…2025/3/21DistributedComputing52Questions1)并行計算與分布式計算區別?2)分布式計算的核心技術是?3)什么是BONIC架構?如何應用在分布式計算應用中?4)有哪些分布式計算模式?舉例說明相關實際應用?5)分布式計算的核心技術是?第2章分布式編程基礎提綱進程間通信Socket編程RMI編程P2P編程進程間通信的定義分布式計算的核心技術是進程間通信(interprocesscommunication,IPC),即在互相獨立的進程(進程是程序的運行時表示)間通信及共同協作以完成某項任務的能力。計算機1計算機2互聯網單播通信與組播通信在分布式計算中,兩個或多個進程按約定的某種協議進行IPC,此處協議是指數據通信各參與進程必須遵守的一組規則。在協議中,一個進程有些時候可能是發送者,在其他時候則可能是接收者。單播組播IPC設施系統級IPC設施消息隊列共享內存。。。高層的IPCAPI抽象開發分布式應用往往工作量比較大且復雜更好地把注意力集中在應用邏輯上API:ApplicationProgrammingInterface,應用編程接口或應用程序接口IPCAPI的四種基本操作發送(Send):該操作由發送進程發起,旨在向接收進程傳輸數據。操作必須允許發送進程識別接收進程和定義待傳數據。接收(Receive):該操作由接收進程發起,旨在接收發送進程發來的數據操作必須允許接收進程識別發送進程和定義保存數據的內存空間,該內存隨后被接收者訪問。連接(Connect):對面向連接的IPC,必須有允許在發起進程和指定進程間建立邏輯連擊的操作:其中以進程發出請求連接操作而另一進程發出接受連接操作。斷開連接(Disconnect):對面向連接的IPC,該操作允許通信的雙方關閉先前建立起來的某一邏輯連接。IPC使用示例:HTTP事件同步IPC中的一個主要難點是進行IPC的各相關進程是獨立執行的,各進程不知道對方進程的情況。協議涉及的雙方必須按特定順序發起IPC操作,否則可能通信失敗。因此,參與通信的兩個進程需要同步他們的操作,由一方發送數據,另一方則需要等待所有數據發送完成時,開始接收數據。IPC設施提供事件同步的最簡單的方法是使用阻塞(blocking)機制或同步(synchronous),即掛起某一進程的執行,直到該進程發起的某個操作執行結束。另外,IPC操作可以是異步(asynchronous)或非阻塞操作(nonblocking)。進程發起的異步操作不會引起阻塞。因此,一旦向IPC設施發出異步操作后,進程可以繼續執行。當該異步操作完成后,進程才會隨后得到IPC設施的通知。IPC范型在最低抽象層,IPC利用底層的串行或并行數據傳輸機制,在連接上傳輸二進制流。例如,這種IPC范型可以用于編寫網絡驅動軟件。這種形式的IPC屬于網絡或操作系統編程領域。下一個抽象層是眾所周知的一種范型,稱作socket應用程序接口(socketAPI)。在socket范型中,兩個進程使用名為socket的邏輯構造交換數據,每一方都要建立一個socket。待發送數據被寫入socket。在另一端,接收進程從自身的socket中讀取或提取數據。遠程過程調用(remoteprocedurecall)或遠程方法調用(remotemethodinvocation)范型通過允許向遠程進程發送過程調用或方法調用,來提供更高層次的抽象。這是,數據作為參數和返回值,在兩個進程間進行傳遞。提綱進程間通信Socket編程RMI編程P2P編程Socket歷史SocketAPI最早作為BerkeleyUnix操作系統的程序庫,出現于20世紀80年代早期,用于提供IPC功能。現在所有主流操作系統都支持SocketAPI。在BSD、Linux等基于Unix的系統中,SocketAPI都是操作系統的一部分。在個人計算機操作系統如MS-DOS、WindowsNT、Mac-OS、OS\2中,SocketAPI都是以程序庫形式提供的(在Windows系統中,SocketAPI稱為Winsocket)。Java語言在設計之初就考慮到了網絡編程,也將SocketAPI作為語言核心類的一部分提供給用戶。所有這些API都使用相同的消息傳遞模型和非常類似的語法。Socket現狀SocketAPI是實現進程間通信的第一種編程設施。SocketAPI非常重要的原因主要有以下兩點:1)SocketAPI已經成為IPC編程事實上的標準,高層IPC設施都是構建于SocketAPI之上的,即它們基于SocketAPI實現的。2)對于響應時間要求較高或在有限資源平臺上運行的應用來說,用SocketAPI實現是最合適的。基本Socket機制兩種主要的傳輸層協議UDP(UserDatagramProtocol,用戶數據包協議):允許使用無連接通信傳輸報文(即在傳輸層發送和接受)。被傳輸報文稱為數據報(datagram)。根據無連接通信協議,每個傳輸的數據包都被分別解析和路由,并且可按任何順序到達接收者。TCP(TransmissionControlProtocol,傳輸控制協議):面向連接的協議,它通過在接受者和發送者之間建立的邏輯連接來傳輸數據流。由于有連接,從發送者到接受者的數據能保證以與發送次序相同的順序被接受。兩種主要的傳輸層協議UDP:如果主機A上的進程1通過順序傳輸數據包m1、m2,向主機B上的進程2發送消息,這些數據包可以通過不同路由在網絡上傳輸,并且可按下列任何一種順序到達接收進程:m1-m2或m2-m1。在數據通信網絡的術語中,“包”(或稱分組,英文為packet)是指在網絡上傳輸的數據單位。每個包中都包含有效數據(載荷,payload)以及一些控制信息(頭部信息),如目的地址。TCP:如果主機A上的進程1順序傳輸m1、m2,向主機B上的進程2發送消息,接收進程可以認為消息將以m1-m2順序到達,而不是m2-m1。兩種類型的Socket根據傳輸層所使用協議不同,SocketAPI分成兩種類型:數據包Socket:即DatagramSocket,一種使用UDP傳輸的Socket。流式Socket:即StreamSocket,使用TCP傳輸的Socket。提示:由于分布式計算與網絡應用主要使用流式Socket比較多,后面將重點討論流式Socket的開發技術。兩種類型的SocketAPI數據報Socket(DatagramSocket)流式Socket(StreamSocket)流式SocketAPIJava流式Socket
API在Java中,有兩個類提供了流式SocketAPI:1)ServerSocket用于接受連接,我們將稱之為連接socket2)Socket用于數據交換,我們將稱之為數據socket流式Socket程序流類ServerSocket的主要方法和構造函數Method/constructorDescriptionServerSocket(int
port)Createsaserversocketonaspecifiedport.Socketaccept()throwsIOExceptionListensforaconnectiontobemadetothissocketandacceptsit.Themethodblocksuntilaconnectionismade.publicvoidclose()throwsIOException
Closesthissocket.voidsetSoTimeout(int
timeout)throwsSocketExceptionSetatimeoutperiod(inmilliseconds)sothatacalltoaccept()forthissocketwillblockforonlythisamountoftime.Ifthetimeoutexpires,ajava.io.InterruptedIOExceptionisraised類Socket的主要方法和構造函數Method/constructorDescriptionSocket(InetAddress
address,int
port)CreatesastreamsocketandconnectsittothespecifiedportnumberatthespecifiedIPaddressvoidclose()throwsIOExceptionClosesthissocket.InputStreamgetInputStream()throwsIOExceptionReturnsaninputstreamsothatdatamaybereadfromthissocket.OutputStream
getOutputStream()throwsIOExceptionReturnsanoutputstreamsothatdatamaybewrittentothissocket.voidsetSoTimeout(int
timeout)throwsSocketExceptionSetatimeoutperiodforblockingsothataread()callontheInputStreamassociatedwiththisSocketwillblockforonlythisamountoftime.Ifthetimeoutexpires,ajava.io.InterruptedIOExceptionisraised流式Socket基本語法//instantiatesasocketforacceptingconnectionServerSocketconnectionSocket=newServerSocket(portNo);SocketdataSocket=connectionSocket.accept();//getaoutputstreamforwritingtothedatasocketOutputStreamoutStream=dataSocket.getOutputStream();PrintWritersocketOutput=newPrintWriter(newOutputStreamWriter(outStream));socketOutput.println(message);socketOutput.flush();dataSocket.close();connectionSocket.close();//instantiatesadatasocketandconnectwithatimeoutSocketAddress
sockAddr=newInetSocketAddress(acceptorHost,acceptorPort);SocketmySocket=newSocket();inttimeoutPeriod=2000;//2secondsmySocket.connect(sockAddr,timeoutPeriod);//getaninputstreamforreadingfromthedatasocketInputStreaminStream=mySocket.getInputStream();BufferedReader
socketInput=newBufferedReader(newInputStreamReader(inStream));Stringmessage=socketInput.readLine();mySocket.close();類Example1ConnectionAcceptor類Example1ConnectionRequestor流式Socket基本語法在本例中有一些值得關注的地方:1)由于這里處理的是數據流,因此可使用Java類PrinterWriter向socket寫數據和使用BufferedReader從流中讀取數據。這些類中所使用的方法與向屏幕寫入一行或從鍵盤讀取一行文本相同。2)盡管本例將Acceptor和Requestor分別作為數據發送者和數據接收者介紹,但兩者的角色可以很容易地進行互換。在那種情況下,Requestor將使用getOutputStream向socket中寫數據,而Acceptor將使用getInputStream從socket中讀取數據。3)事實上,任一進城都可以通過調用getInputStream和getOutputStream從流中讀取數據或向其中寫入數據。4)在本例中,每次只讀寫一行數據(分別使用readLine和println方法),但其實也可以每次只讀寫一行中的一部分數據(分別使用read和print方法來實現)。然而,對于以文本形式交換消息的文本協議來說,每次讀寫一行是標準做法。事件狀態圖隱藏數據Socket細節publicclassExample2ConnectionAcceptor{publicstaticvoidmain(String[]args){…
ServerSocketconnectionSocket=newServerSocket(portNo);MyStreamSocketdataSocket=newMyStreamSocket(connectionSocket.accept());dataSocket.sendMessage(message);dataSocket.close();connectionSocket.close();…}//endmain}//endclass類Example2ConnectionAcceptor類Example2ConnectionRequestorpublicclassExample2ConnectionRequestor{publicstaticvoidmain(String[]args){…
MyStreamSocket
mySocket=newMyStreamSocket(acceptorHost,acceptorPort);Stringmessage=mySocket.receiveMessage();
mySocket.close();…}//endmain}//endclassMyStreamSocket類實現細節publicclassMyStreamSocketextendsSocket{privateSocketsocket;privateBufferedReaderinput;privatePrintWriteroutput;
MyStreamSocket(InetAddress
acceptorHost,intacceptorPort)throwsSocketException,IOException{socket=newSocket(acceptorHost,acceptorPort);
setStreams();}
MyStreamSocket(Socketsocket)throwsIOException{
this.socket=socket;
setStreams();}privatevoidsetStreams()throwsIOException{//getaninputstreamforreadingfromthedatasocket
InputStream
inStream=socket.getInputStream();input=newBufferedReader(newInputStreamReader(inStream));
OutputStream
outStream=socket.getOutputStream();output=newPrintWriter(newOutputStreamWriter(outStream));//createaobjectforcharacter-modeoutput}publicvoidsendMessage(Stringmessage)throwsIOException{
output.println(message);
output.flush();}//endsendMessagepublicStringreceiveMessage()throwsIOException{//readalinefromthedatastreamStringmessage=input.readLine();returnmessage;}//endreceiveMessage}//endclass提綱進程間通信Socket編程RMI編程P2P編程RMI的定義RMI是RemoteMethodInvocation的縮寫,即遠程方法調用。RMI是RPC模型的面向對象實現,是一種用于實現遠程過程調用的應用程序編程接口,它使客戶機上運行的程序可以調用遠程服務器上的對象。JavaRMI由于RMIAPI只適用于Java程序,所以,我們一般稱為JavaRMI。但該API相對簡單,因此,非常適合于用作學習網絡應用中分布式對象技術的入門資料。
JavaRMI使用接口化編程。在需要服務端的某一個遠程對象時,編程人員通過定義一個該對象的接口來隱藏它的實現,并在客戶端定義一個相同的接口,客戶端使用該接口可以像本地調用一樣實現遠程方法調用。通過調用RMI的API,對象服務器通過目錄服務導出和注冊遠程對象,這些對象提供一些可以被客戶程序調用的遠程方法。從語法上來看,RMI通過遠程接口聲明遠程對象,該接口是Java接口的擴展;遠程接口由對象服務器實現;對象客戶使用與本地方法調用類似的語法訪問遠程對象,并調用遠程對象的方法。JavaRMI體系結構從應用層看,RMI由客戶應用、服務器應用和對象目錄服務3個部分。RMI系統實現架構由三層組成:樁/框架(Stub/Skeleton)層:客戶端的樁和服務器端的框架;遠程引用(remotereference)層:處理遠程引用行為;傳輸層(transport):連接的建立和管理,以及遠程對象的跟蹤。RMI基本分布式應用遠程接口定義服務器端軟件客戶端軟件RMI基本分布式應用:遠程接口定義在RMIAPI中,分布式對象的創建開始于遠程接口。Java接口是為其他類提供模板的一種類:它包括方法聲明或簽名,其實現由實現該接口的類提供。Java遠程接口是繼承Java類remote的一個接口,該類允許使用RMI語法實現接口。與必須為每個方法簽名定義擴展和RemoteException不同,遠程接口語法與常規或本地Java接口相同。RMI基本分布式應用:遠程接口定義importjava.rmi.*;publicinterfaceSomeInterface
extendsRemote{//signatureoffirstremotemethodpublicStringsomeMethod1()throwsjava.rmi.RemoteException;//signatureofsecondremotemethodpublicintsomeMethod2(intx)throwsjava.rmi.RemoteException;//signatureofotherremotemethodsmayfollow}//endinterfaceRMI基本分布式應用:服務器端軟件對象服務器是指這樣的一種對象,它可以提供某一分布式對象的方法和接口。每個對象服務器必須:1)實現接口部分定義的每個遠程方法;2)向目錄服務注冊包含了實現的對象。RMI基本分布式應用:服務器端軟件import
java.rmi.*;import
java.rmi.server.*;publicclassSomeImplextendsUnicastRemoteObject
implementsSomeInterface{publicStringsomeMethod1()throwsRemoteException{//codetobesupplied}publicintsomeMethod2()throwsRemoteException{//codetobesupplied}}//endclass1)遠程接口實現遠程接口實現類的一個通用模板RMI基本分布式應用:服務器端軟件1)遠程接口實現import
java.rmi.*;import
java.rmi.server.*;publicclassHelloImplextendsUnicastRemoteObjectimplementsHelloInterface{publicHelloImpl()throwsRemoteException{super();}publicStringsayHello(Stringname)throwsRemoteException{return"WELCOMETORMI!Goodafternoon!"+name+".";}}//endclassRMI基本分布式應用:服務器端軟件1)遠程接口實現RMI基本分布式應用:服務器端軟件2)stub和skeleton生成在RMI中,分布式對象需要為每個對象服務器和對象客戶提供代理,分別成為對象skeleton和stub。這些代理可通過使用JavaSDK提供的RMI編譯器rmic,編譯遠程接口實現生成。可在命令行下輸入下述命令生成stub和skeleton文件:rmic<classnameoftheremoteinterfaceimplementation>例如:rmicSomeImplRMI基本分布式應用:服務器端軟件2)stub和skeleton生成如果編譯成功,將生成兩個代理文件,每個文件的名都以實現類的類名為前綴:SomeImpl_stub.classSomeImpl_skel.class但在Java2版本以上的平臺下,只生成stub文件。對象的stub文件及遠程接口文件,必須被每個對象客戶所共享:這些文件是編譯客戶程序時所必須的文件。可以手工為對象客戶提供每個文件的一個拷貝。此外JavaRMI具有stub下載特征,允許客戶端動態獲取stub文件。RMI基本分布式應用:服務器端軟件3)對象服務器的實現SomeImplexportedObj=newSomeImpl();startRegistry(1234);registryURL="rmi://localhost:"+portNum+"/some";Naming.rebind(registryURL,exportedObj);listRegistry(registryURL);主機名
端口號引用名類Naming提供從注冊表獲取和存儲引用的方法。具體來說,rebind方法允許如下形式URL將對象引用存儲到注冊表中:主機名應該是服務器名,或簡寫成localhost,引用名指用戶選擇的名稱,該名稱在注冊表中應該是惟一的。rebind方法將覆蓋注冊表中與給定引用名綁定的任何引用。如果不希望覆蓋,可以使用bind方法。URL:rmi://<hostname>:<portnumber>/<referencename>//檢查RMI注冊表當前是否運行在默認端口上。如果不在,RMI注冊表將被激活。RMI基本分布式應用:服務器端軟件3)對象服務器的實現此外,可以使用JDK中的rmiregistry工具在系統提示符輸入下列命令,手工激活RMI注冊表:rmiregistry<portnumber>
端口號(默認1099)RMI對象服務器是并發服務器:每個對象客戶請求都使用服務器上的一個獨立線程服務。由于遠程方法調用可并發執行,因此遠程對象實現的線程安全性非常重要。RMI基本分布式應用:服務器端軟件3)對象服務器的實現RMI基本分布式應用:客戶端軟件查找遠程對象:如果對象服務器先前在注冊表中保存了對象引用,可以用類Naming的lookup方法獲取這些引用。注意,應將獲取的引用傳給遠程接口類。StringregistryURL="rmi://localhost:"+portNum+"/some";SomeInterfaceh=(SomeInterface)Naming.lookup(registryURL);調用遠程方法:遠程接口引用可以調用遠程接口中的任何方法,例如:Stringmessage=h.method1();System.out.println(message);注意,調用遠程方法的語法與調用本地方法相同。RMI應用構建步驟總結1)服務器端軟件開發算法為該應用的所有待生成文件創建一個目錄。在SomeInterface.java中定義遠程服務器接口。編譯并修改程序,直到不再有任何語法錯誤。SomeImpl.java中實現接口,編譯并修改程序,直到不再有任何語法錯誤。使用RMI編譯器rmic處理實現類,生成遠程對象的stub文件
rmicSomeImpl可以從目錄中看到新生成文件SomeImpl_Stub.class,每次修改接口實現時,都要重新執行步驟3和步驟4創建對象服務器程序SomeServer.java,編譯并修改程序,直到不再有任何語法錯誤。激活對象服務器javaSomeServerRMI應用構建步驟2)客戶端軟件開發算法為該應用的所有待生成文件創建一個目錄獲取遠程接口類文件的一個拷貝,也可獲取遠程接口源文件的一個拷貝,使用javac編譯程序,生成接口文件。獲取接口實現stub文件SomeImpl_stub.class的一個拷貝開發客戶程序SomeClient.java,編譯程序,生成客戶類激活客戶javaSomeClientRMI應用構建步驟2)客戶端軟件開發算法客戶類程序與任何其他Java類相似。RMI所需的語法包括定位服務器主機的RMI注冊表和查找服務器對象的遠程引用;該引用隨后可被傳到遠程接口類和被調用的遠程方法查找遠程對象:如果對象服務器先前在注冊表中保存了對象引用,可以用類Naming的lookup方法獲取這些引用。注意,應將獲取的引用傳給遠程接口類。
StringregistryURL="rmi://localhost:"+portNum+"/some";
SomeInterfaceh=(SomeInterface)Naming.lookup(registryURL);調用遠程方法:遠程接口引用可以調用遠程接口中的任何方法,例如:
Stringmessage=h.method1();System.out.println(message);注意,調用遠程方法的語法與調用本地方法相同。RMI應用構建步驟2)客戶端軟件開發算法基本RMI應用程序演示RMI應用的HelloWorld實現程序:HelloInterface.javaHelloImpl.javaHelloServer.javaHelloClient.javaHelloWorld程序演示RMI應用構建步驟3)測試和調試構建最小RMI程序的一個模板。從一個遠程接口開始,其中包括一個方法簽名,一個stub實現,一個輸出對象的服務器程序以及一個足以用來調用遠程方法的客戶程序。在單機上測試模板程序,直到遠程方法調用成功。每次在接口中增加一個方法簽名。每次增加后都修改客戶程序來調用新增方法。完善遠程方法定義內容,每次只修改一個。在繼續下一個方法之前,測試并徹底調試每個新增方法。完全測試所有遠程方法后,采用增量式方法開發客戶應用。每次增加后,都測試和調試程序。將程序部署到多臺機器上,測試并調試。RMI和socketAPI的比較遠程方法調用API作為分布式對象計算范型的代表,是構建網絡應用的有效工具。它可用來取代socketAPI快速構建網絡應用。在RMIAPI和socketAPI之間權衡時,需要考慮以下因素:1)socketAPI的執行與操作系統密切相關,因此執行開銷更小,RMI需要額外的中間件支持,包括代理和目錄服務,這些不可避免地帶來運行時開銷。對有高性能要求的應用來說,socketAPI仍將是惟一可行途徑。2)RMIAPI提供了使軟件開發任務更為簡單的抽象。用高級抽象開發的程序更易理解,因此也更易調試。RMI和socketAPI的比較由于運行在低層,socketAPI通常是平臺和語言獨立的,RMI則不一定。例如JavaRMI需要特定的Java運行時支持。結果是,使用JavaRMI實現的應用必須用Java編寫,并且也只能運行在Java平臺上。在設計應用系統時,是否能選擇適當的范型和API是非常關鍵的。依賴于具體環境,可以在應用的某些部分使用某種范型或API,而在其他部分使用另一種范型或API。由于使用RMI開發網絡應用相對簡單,RMI是快速開發應用原型的一個很好的候選工具。提綱進程間通信Socket編程RMI編程P2P編程P2P的定義P2P,即Peer-to-Peer的縮寫,常稱它為“點對點”或者“端對端”,而學術界常稱它為“對等計算”。P2P是一種以非集中化方式使用分布式資源來完成計算任務的一種分布式計算模式。非集中化:P2P系統中并非采用傳統的以服務器為中心管理所有客戶端的方法,而是消除“中心”的概念,將原來的客戶端視為服務器和客戶端的綜合體;分布式資源:P2P系統的參與者共享自己的一部分空閑資源供系統處理關鍵任務所用,這些資源包括處理能力、數據文件、數據存儲和網絡帶寬等。P2P的優點P2P技術打破了傳統的Client/Server(縮寫為C/S)模式,在P2P網絡中所有結點的地位都是對等的,每個結點既充當服務器,又充當客戶端,這樣緩解了中心服務器的壓力,使得資源或任務處理更加的分散化。由于P2P網絡中結點是Client和Server的綜合體,因此結點也被形象地稱為“SERVENT”。C/S模式與P2P模式對比C/S模式P2P模式C/S模式與P2P模式對比C/S模式:服務器和客戶端之間是一對多的主從關系,系統的信息和數據都保存在中心服務器上若要索取信息,必須先訪問服務器,才能得到所需的信息,且客戶端之間是沒有交互能力的。P2P模式:不區分提供信息的服務器和請求信息的客戶端,每一個結點都是信息的發布者和請求者,對等結點之間可以實現自治交互,無需使用服務器。每個對等結點都可以在網絡中發布和分享信息,使得網絡中閑散的資源得到充分利用。不需要花費高昂的費用來維護中心服務器。基于P2P范型的即時聊天系統開發由于演示的是簡單的P2P即時聊天系統,所以,我們僅僅設計了如下幾個功能:(1)點對點單人聊天;(2)多人同時在線聊天;(3)用戶可以自由加入和退出系統;(4)具備用戶在線狀態監視。1)確定系統實現功能為了更好地理解P2P分布式計算模式和P2P應用的開發方法,本節使用JavaSocket來實現一個簡單的基于P2P范型的即時聊天系統。系統的功能基于P2P范型的即時聊天系統開發為了簡單起見,我們采用類似于中心化拓撲結構的P2P模式,所有客戶都需要與中心服務器相連,并將自己的網絡地址寫入服務器中,服務器只需要監聽和更新用戶列表信息,并發送給客戶最新的用戶列表信息即可。當需要點對點聊天時,客戶端只需要從本地用戶列表中讀取目標用戶的網絡地址,并連接目標用戶,即可實現通信。因為是P2P系統,客戶端要同時扮演服務器和客戶端兩個角色,所以,用戶登錄后都會創建一個接收其他用戶連接的監聽線程,以實現服務器的功能。2)確定P2P模式基于P2P范型的即時聊天系統開發創建Socket、綁定地址和端口號,監聽并接受客戶端的連接請求。服務器端在客戶連接后自動獲取客戶端用戶名、IP地址和端口號,并將其保存在服務器端的用戶列表中,同時更新所有在線用戶的客戶端在線用戶列表信息,以方便客戶了解上下線的實時情況,以進行聊天。當有用戶下線時,服務器端要能即時監聽到,并更新用戶列表信息,發送給所有在線客戶端。對在線用戶數量進行統計。3)確定服務器主要任務基于P2P范型的即時聊天系統開發客戶端創建Socket,并調用connect()函數,向中心服務器發送連接請求。客戶端在登錄后也必須充當服務器,以接收其他用戶的連接請求,所有需要創建一個用戶接收線程來監聽。用戶登錄后需要接收來自服務器的所有在線用戶信息列表,并更新本地的用戶列表信息,以方便選擇特定用戶進行聊天。客戶端可以使用群發功能,向在線用戶列表中的所有用戶發送聊天信息。4)確定客戶端主要任務基于P2P范型的即時聊天系統開發服務器主要任務客戶端主要任務創建Socket、綁定地址和端口號,監聽并接受客戶端的連接請求自動獲取客戶端用戶名、IP地址和端口號,并將其保存在服務器端的用戶列表中,同時更新所有在線用戶的客戶端在線用戶列表信息當有用戶下線時,服務器端要能即時監聽到,并更新用戶列表信息,發送給所有在線客戶端。對在線用戶數量進行統計。創建Socket,并調用connect()函數,向中心服務器發送連接請求。在登錄后也必須充當服務器,接收其他用戶的連接請求,需要創建一個用戶接收線程來監聽用戶登錄后需要接收來自服務器的所有在線用戶信息列表,并更新本地的用戶列表信息客戶端可以使用群發功能,向在線用戶列表中的所有用戶發送聊天信息注意,服務器向所有客戶發送最新用戶列表信息,及客戶端的群發功能,都是通過簡單地遍歷用戶列表來實現。基于P2P范型的即時聊天系統開發中心服務器啟動后會自動創建一個監聽線程,以接受客戶端發來的連接請求。當客戶端與服務器連接后,客戶端會將自己的信息(用戶名、IP地址和端口號等)寫入socket,服務器端從此socket中讀取該用戶信息,并登記到用戶信息列表中。然后,服務器將最新的用戶信息列表群發給所有在線的客戶端,以便客戶端得到最新的用戶列表。步驟1、2展示了客戶登陸服務器的過程。5)確定交互過程:登陸基于P2P范型的即時聊天系統開發每個連接到中心服務器的客戶都會得到最新的用戶信息列表。如步驟3所示,若Client2欲與Client3聊天,則Client2檢索自己的用戶信息列表,得到Client3的用戶信息后,便可與Client3進行連接,實現通信。此過程,并不需要中心服務器的干預。5)確定交互過程:通信基于P2P范型的即時聊天系統開發當有一個客戶需要下線時,例如圖中的Client1,那么Client1首先將下線請求寫入socket,中心服務器接收到含有下線請求標記的信息后,Client1便通過握手機制下線(為了安全關閉socket)。Client1安全下線后,中心服務器會將Client1的用戶信息從在線列表中刪除,并將更新后的用戶列表、下線用戶名稱和當前網絡的在線用戶情況等群發給所有在線客戶端,以便客戶端得到最新的在線用戶列表。5)確定交互過程:登出基于P2P范型的即時聊天系統開發客戶端的群發功能與服務器端的群發類似,都采用遍歷用戶列表的方法。例如,圖中Client3欲與所有在線用戶聊天,則只要遍歷Client3的在線用戶列表,與所有在線用戶進行連接,便可以進行群聊。5)確定交互過程:群聊基于P2P范型的即時聊天系統開發6)系統實現類圖基于P2P范型的即時聊天系統開發7)確定系統界面:Server端基于P2P范型的即時聊天系統開發7)確定系統界面:Client端基于P2P范型的即時聊天系統開發8)主要類實現說明1)首先設計中心服務器和客戶端系統界面。創建中心服務器Server類,派生自JFrame類。同樣,創建客戶端Client類,也派生自JFrame類。Server和Client都需要實現ActionListener接口,從而對界面上的按鈕等動作進行監聽。2)創建P2P網絡結點Node類,其中包含用戶名、IP地址、端口號和一個結點變量next。3)創建RandomPort類用于客戶端分配隨機可用端口號。4)創建用戶列表類UserInfo,它用于維護中心服務器端和客戶端的在線用戶信息。5)實現中心服務器Server類,Server類中除了包含系統界面上的一些組件成員外,還有用于維護在線用戶信息的UserInfo對象、用于連接的ServerSocket對象和Socket對象,及用于套接字輸入、出流的對象。6)創建Server端用于與客戶端連接的線程ServerReceiveThread類,它主要負責接受客戶端的連接請求、更新在線用戶列表,并發送給所有客戶端等。基于P2P范型的即時聊天系統開發8)主要類實現說明7)實現客戶端Client類,除了包含界面上所示的一些組件成員外,還包括用于連接的套接字對象、套接字輸入出流、接收其他客戶端連接請求的線程對象等。客戶端的主要行為包括處理界面按鈕產生的動作、給點對點用戶或所有用戶發送信息、及一個用于與服務器連接,并獲取服務器更新用戶列表的內部類ComWithServer。8)創建ComWithServer類,它主要負責與服務器連接、創建客戶端接收線程、更新用戶信息等。9)創建客戶端信息接收線程類ClientReceiveThread,當一個Client創建時,會同時為此客戶創建一個接收線程,以把自己當做服務器,接收來自其他客戶端的聊天信息。10)客戶端還需要創建一個線程用于發送自己的信息給連接的類一端,因此創建客戶端發送線程ClientSendThread類,它的成員主要包括連接地址、端口、及發送信息,run方法主要負責獲取連接的輸入出流,然后將自己的聊天信息,寫入流中即可。基于P2P范型的即時聊天系統開發9)系統運行詳細過程當單擊“啟動服務器”按鈕時,會觸發調用類Server的startServer()方法,該方法為服務器選定特定的端口號,并創建服務器端監聽線程serverListenThread(服務器端監聽線程類ServerListenThread的一個實例),等待客戶端的連接請求。同時,服務器還會創建一個線程ServerReceiveThread,用于接收客戶端發來的下線請求,并將更新后的用戶列表群發給所有用戶。當客戶端與服務器連接后,會創建一個線程ComWithServer,用于將自己的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 檔口入股合同協議書
- 裝修合同變更協議書范本
- 轉讓檔口合同協議書
- 房屋拆除貨幣合同協議書
- 安全旅行課件
- 自建舊房拆除合同協議書
- 貨車運營合作合同協議書
- 軟件購買合同協議書范本
- 中國塑料防盜瓶蓋項目創業計劃書
- 保潔解除合同協議書
- 中國建行存單英文翻譯
- 事業單位工作人員調動審批表格
- 八年級英語-多維閱讀Skycar示范課教學設計1
- 醫院基建科各項工作風險分析
- 國家開放大學一網一平臺電大《建筑測量》實驗報告1-5題庫
- 對外投資合作國別(地區)指南 -柬埔寨-20230619-00335
- (新平臺)國家開放大學《建設法規》形考任務1-4參考答案
- 關于熊貓的資料
- 華為認證HCIP安全V4.0-H12-725考試復習題庫大全-上(單選、多選題)
- 華為認證HCIP安全V4.0-H12-725考試復習題庫大全-下(判斷、填空、簡答題)
- 醫院院長任期經濟責任審計述職報告材料
評論
0/150
提交評論