1.1.3.1.2 網(wǎng)絡(luò)I/O:Socket→RMI
★Socket
Socket編程可能大家都很熟,所以就不多討論了,只是說通過socket把數(shù)據(jù)保存到遠端服務(wù)器或從網(wǎng)絡(luò)socket讀取數(shù)據(jù)也不失為一種值得考慮的方式。
★RMI
RMI機制其實就是RPC(遠程過程調(diào)用)的Java版本,它使用socket作為基本傳輸手段,同時也是序列化最重要的一個應(yīng)用,F(xiàn)在網(wǎng)絡(luò)傳輸從編程的角度來看基本上都是以流的方式操作,socket就是一個例子,將對象轉(zhuǎn)換成字節(jié)流的一個重要目標就是為了方便網(wǎng)絡(luò)傳輸。
想象一下傳統(tǒng)的單機環(huán)境下的程序設(shè)計,對于Java語言的函數(shù)(方法)調(diào)用(注意與C語言函數(shù)調(diào)用的區(qū)別)的參數(shù)傳遞,會有兩種情況:如果是基本數(shù)據(jù)類型,這種情況下和C語言是一樣的,采用值傳遞方式;如果是對象,則傳遞的是對象的引用,包括返回值也是引用,而不是一個完整的對象拷貝!試想一下在不同的虛擬機之間進行方法調(diào)用,即使是兩個完全同名同類型的對象他們也很可能是不同的引用!此外對于方法調(diào)用過程,由于被調(diào)用過程的壓棧,內(nèi)存“現(xiàn)場”完全被被調(diào)用者占有,當被調(diào)用方法返回時,才將調(diào)用者的地址寫回到程序計數(shù)器(PC),恢復調(diào)用者的狀態(tài),如果是兩個虛擬機,根本不可能用簡單壓棧的方式來保存調(diào)用者的狀態(tài)。因為種種原因,我們才需要建立RMI通信實體之間的“代理”對象,譬如“存根”就相當于遠程服務(wù)器對象在客戶機上的代理,stub就是這么來的,當然這是后話了。
本地對象與遠程對象(未必是物理位置上的不同機器,只要不是在同一個虛擬機內(nèi)皆為“遠程”)之間傳遞參數(shù)和返回值,可能有這么幾種情形:
· 值傳遞:這又包括兩種子情形:如果是基本數(shù)據(jù)類型,那么都是“可序列化”的,統(tǒng)統(tǒng)序列化成可傳輸?shù)淖止?jié)流;如果是對象,而且不是“遠程對象”(所謂“遠程對象”是實現(xiàn)了java.rmi.Remote接口的對象),本來對象傳遞的應(yīng)該是引用,但由于上述原因,引用是不足以證明對象身份的,所以傳遞的仍然是一個序列化的拷貝(當然這個對象也必須滿足上述“可序列化”的條件)。
· 引用傳遞:可以引用傳遞的只能是“遠程對象”。這里所謂的“引用”不要理解成了真的只是一個符號,它其實是一個留在(客戶機)本地stub中的,和遠端服務(wù)器上那個真實的對象張得一模一樣的鏡像而已!只是因為它有點“特權(quán)”(不需要經(jīng)過序列化),在本地內(nèi)存里已經(jīng)有了一個實例,真正引用的其實是這個“孿生子”。
由此可見,序列化在RMI當中占有多么重要的地位。
相關(guān)推薦:計算機等級考試二級Java經(jīng)典算法大全匯總北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |