專利名稱::基于nio和io的面向發(fā)布訂閱系統(tǒng)的傳輸方法
技術(shù)領(lǐng)域:
:本發(fā)明涉及數(shù)據(jù)傳輸領(lǐng)域,主要是一種基于NIO和IO的面向發(fā)布訂閱系統(tǒng)的傳輸方法。
背景技術(shù):
:發(fā)布/訂閱(publish/subscribe,簡稱pub/sub)系統(tǒng)是一種分布式中間件系統(tǒng),是隨著復(fù)雜大規(guī)模的網(wǎng)絡(luò)計(jì)算而出現(xiàn)的一種技術(shù),用于為分布式系統(tǒng)中的各參與者提供一種松耦合的通信方式。在大規(guī)模、高度動(dòng)態(tài)的分布式系統(tǒng)中,參與者在時(shí)間以及空間位置上通常都是動(dòng)態(tài)變化的,比如在出差途中使用掌上電腦等移動(dòng)設(shè)備,頻繁的加入和退出網(wǎng)絡(luò),因此需要一種松耦合的方式參與消息交互和協(xié)同工作。而發(fā)布/訂閱系統(tǒng)的松耦合的特性,恰能解決這個(gè)問題。如圖1所示,一個(gè)發(fā)布/訂閱系統(tǒng)中一般由消息生產(chǎn)者(publisher),消息消費(fèi)者(subscriber)和事件通知服務(wù)組成。在發(fā)布/訂閱系統(tǒng)中,消息通常被稱為"事件",消息生產(chǎn)者將"事件"發(fā)送給事件通知服務(wù);消息消費(fèi)者則向事件通知服務(wù)發(fā)出一個(gè)"訂閱條件",表示對(duì)系統(tǒng)的哪些事件感興趣;而事件通知服務(wù)則保證將發(fā)布的事件及時(shí)、可靠地送給所有感興趣的消息消費(fèi)者。而發(fā)布者和消費(fèi)者在進(jìn)行消息交互時(shí),都不需要知道對(duì)方的存在,使得它們?cè)跁r(shí)間和空間被完全解耦,從而能夠滿足大規(guī)模、動(dòng)態(tài)的分布式系統(tǒng)的需要。而在傳統(tǒng)的發(fā)布/訂閱系統(tǒng)中,事件的生產(chǎn)者和消費(fèi)者之間的傳輸多采用基于java的老式IO(輸入/輸出)方式。在這種方式中,服務(wù)端將在開始時(shí)建立一個(gè)監(jiān)聽socket(套接字),socket是主要用來進(jìn)行客戶端和服務(wù)器端通訊的工具,當(dāng)簡歷一個(gè)監(jiān)聽socket后,就等待客戶端請(qǐng)求,客戶連接后,產(chǎn)生會(huì)話,會(huì)話完成后,關(guān)閉連接;而客戶端通過socket對(duì)服務(wù)端發(fā)出連接請(qǐng)求,一旦連接成功,打開會(huì)話,會(huì)話完成,關(guān)閉socket。在這種傳輸系統(tǒng)中,系統(tǒng)的瓶頸通常在10讀寫方面,在打開一個(gè)IO通道后,read()方法將一直等待在端口一邊讀取字節(jié)內(nèi)容,如果沒有內(nèi)容進(jìn)來,read()也是一直等待,這會(huì)影響我們程序繼續(xù)做其他事情,那么改進(jìn)做法就是開設(shè)線程,讓線程去等待,但是這樣做也是相當(dāng)耗費(fèi)資源的,尤其是在大規(guī)模分布式系統(tǒng)中,如果我們要接受大量的客戶端的連接,必須要開設(shè)大量的線程,而這將是對(duì)資源的嚴(yán)重浪費(fèi)。而基于java的NIO(newIO)的出現(xiàn),則改變了這種現(xiàn)狀,使網(wǎng)絡(luò)傳輸?shù)膮f(xié)議不再集中在IO讀寫上。NIO最大的特點(diǎn)有兩個(gè)一個(gè)是塊狀讀寫;另外一個(gè)是多路復(fù)用技術(shù)(multiplex)。第一個(gè)特點(diǎn)改變了老式10中,每次讀寫只有一個(gè)字節(jié)(stream)或兩個(gè)字節(jié)(reader)的方式,提高了讀寫的速度;第二個(gè)特點(diǎn)改變了原來讀寫socket時(shí)候阻塞的同步狀況,使socket的讀寫具有異步的功能。JavaNIO非阻塞技術(shù)實(shí)際是采取Reactor模式,或者說是Observer模式為我們監(jiān)察IO端口,如果有內(nèi)容進(jìn)來,會(huì)自動(dòng)通知我們,這樣,我們就不必開啟多個(gè)線程死等,從外界看,實(shí)現(xiàn)了流暢的IO讀寫,不堵塞了。NK)有一個(gè)主要的類Selector,這個(gè)類就好像一個(gè)觀察者,只要我們把需要探知的socketchannel(套接字通道)告訴Selector,我們接著做別的事情,當(dāng)有事件發(fā)生時(shí),他會(huì)通知我們,傳回一組SelectionKey,我們讀取這些Key,就會(huì)獲得我們剛剛注冊(cè)過的socketchannel,然后,我們從這個(gè)Channel中讀取數(shù)據(jù),放心,包準(zhǔn)能夠讀到,接著我們可以處理這些數(shù)據(jù)。在我們使用NIO的時(shí)候,cpu時(shí)間多會(huì)消耗在Selector的select操作上(NIO的多路復(fù)用),而select操作主要調(diào)用的是poll函數(shù),這個(gè)操作是一個(gè)輪詢socket的同步操作,它的主要功能就是不斷地去查詢向該選擇器注冊(cè)的socket,看看有沒有可做的操作,如有,則返回,沒有,繼續(xù)不斷地輪詢。也就說,分配的cpu的時(shí)間基本上被消耗在poll上了。之所以如此,是因?yàn)闆]有東西可以寫入或從socket中讀??;那么,就應(yīng)該給"提供讀寫數(shù)據(jù)的線程"更多的cpu時(shí)間,使得每一次的poll都有可作的操作,使時(shí)間耗費(fèi)在讀寫socket之上,而不是poll之上。然而,從實(shí)際情況中看來,poll線程顯然比"提供讀寫數(shù)據(jù)的線程(wr線程)"占用了更多的cpu時(shí)間,假設(shè)他們的優(yōu)先級(jí)相同,也假設(shè)操作系統(tǒng)是公平的分配cpu時(shí)間,那么它們得到的cpu時(shí)間應(yīng)該是一樣的,此時(shí),造成它們占用cpu時(shí)間不同的原因就很可能是這樣在相同的時(shí)間內(nèi),wr線程提供的數(shù)據(jù)量根本不夠poll線程處理,poll線程處理在相同的時(shí)間內(nèi)處理這些數(shù)據(jù)綽綽有余,那么,poll線程更多的時(shí)間就耗費(fèi)在輪詢上了。到這里,我們假設(shè)的是這兩個(gè)線程分配到了相同的時(shí)間,所以,即使poll線程大部分時(shí)間是在做poll輪詢操作,那么所占用的時(shí)間最大值也是有限的,不會(huì)超過線程分配得到的時(shí)間。但是,如果此時(shí)盡管wr線程得到了cpu時(shí)間,但是它在處理過程中主動(dòng)放棄cpu(比如執(zhí)行wait操作),那么,在cpu時(shí)間總量相等的情況下,由于poll線程沒有執(zhí)行wait操作,因此,就會(huì)得到更多的cpu時(shí)間,這樣,大部分的cpu時(shí)間都給poll的輪詢操作了。如果我們可以如果使wr線程不斷的運(yùn)行,而使poll線程在沒有數(shù)據(jù)的時(shí)候放棄cpu時(shí)間,就應(yīng)該可以減少poll線程的輪詢操作,而使wr線程得到更多的cpu時(shí)間,提供更多的可供讀寫的數(shù)據(jù),提高讀寫的效率。然而,由于poll輪詢操作是一個(gè)不間斷的過程,是sun公司提供的底層的api,是無法修改的。所以,就要放棄poll操作,也就是要放棄選擇器。
發(fā)明內(nèi)容本發(fā)明要解決上述技術(shù)所存在的缺陷,提供一種基于NIO和IO的面向發(fā)布訂閱系統(tǒng)的傳輸方法。本發(fā)明解決其技術(shù)問題所采用的技術(shù)方案這種基于NIO和IO的面向發(fā)布訂閱系統(tǒng)的傳輸方法,我們的傳輸協(xié)議在服務(wù)端摒棄老式的基于流的IO,而采用了JDK1.4中的NIO,而在客戶端仍采用老式的I/O。在服務(wù)端我們啟用唯一的接收socket連接的線程,這個(gè)接收線程包含有一個(gè)Selector對(duì)象和一個(gè)讀線程組和寫線程組,Selector對(duì)象主要從客戶端捕捉到各種事件(比如向服務(wù)器端寫入數(shù)據(jù)),讀線程組和寫線程組用來接收來自客戶端的socket連接以及向客戶端寫入數(shù)據(jù),這個(gè)Selector對(duì)象注冊(cè)了一個(gè)ServerSocketChannel(服務(wù)器套接字通道)對(duì)象,這個(gè)ServerSocketChannel對(duì)象用來接收來自客戶端的socket連接。每個(gè)讀線程或?qū)懢€程分別對(duì)應(yīng)一個(gè)socket連接,并將每次接收到的socket都封裝起來成為一個(gè)可讀寫數(shù)據(jù)的SelectableChannel對(duì)象,調(diào)用Java的regist()函數(shù)將其再注冊(cè)到唯一的Selector對(duì)象上,當(dāng)客戶端連接關(guān)閉的時(shí)候,將連接從讀寫線程中注銷,注銷后,讀寫線程則可以綁定新的連接,這樣就可以使用固定數(shù)目的線程處理任意多的客戶端連接。對(duì)于選中的用來讀寫數(shù)據(jù)的Channel(通道),包括ReadableByteChannel(讀通道,用來從客戶端讀取數(shù)據(jù))和WritableByteChannel(寫通道,用來向客戶端寫入數(shù)據(jù))進(jìn)行的操作是非阻塞的,因而所有的線程都可以真正用來發(fā)送、接收消息。在客戶端連接數(shù)量很大的情況下,NIO可以保證線程上下文切換時(shí)較小的開銷。而在客戶端,因?yàn)槲覀兠總€(gè)客戶端一般只有一個(gè)到服務(wù)端的連接,所以摒棄NIO,釆用老式IO操作。主要過程包括如下步驟1)啟動(dòng)服務(wù)器端接收SocketChannel連接的接收線程,并啟動(dòng)讀、寫線程組;2)客戶端進(jìn)行操作時(shí),打開一個(gè)Socket連接到服務(wù)器端,服務(wù)器端的接收線程開始接收連接,并把接收到的SocketChannd向服務(wù)器端的讀寫線程注冊(cè),即將連接的SocketChannel綁定到讀寫線程上;3)客戶端將要發(fā)送的消息作為數(shù)據(jù)報(bào)的一部分,每個(gè)數(shù)據(jù)報(bào)格式為數(shù)據(jù)報(bào)頭、消息體,其中數(shù)據(jù)報(bào)頭包含一個(gè)特殊的標(biāo)志符和表示消息大小的一個(gè)整數(shù),而后將數(shù)據(jù)報(bào)加碼為二進(jìn)制流,然后通過Socket調(diào)用write()函數(shù)將數(shù)據(jù)報(bào)發(fā)送到服務(wù)器端;4)服務(wù)器端讀線程從Socket中讀取標(biāo)志數(shù)據(jù)報(bào)的二進(jìn)制流,如讀取數(shù)據(jù)為數(shù)據(jù)報(bào)頭,則新建一個(gè)數(shù)據(jù)報(bào),并將此流解碼為數(shù)據(jù)報(bào);然后服務(wù)器處理此數(shù)據(jù)報(bào),并生成返回客戶端的數(shù)據(jù)報(bào),利用NIO的WriteableByteChannel,將處理后得到的數(shù)據(jù)報(bào)加碼后變?yōu)槎M(jìn)制流,發(fā)送到客戶端;5)客戶端從Socket讀取此二進(jìn)制流,同上解碼為數(shù)據(jù)報(bào),并根據(jù)數(shù)據(jù)報(bào)格式判斷數(shù)據(jù)報(bào)是否需要客戶端處理器進(jìn)行處理,如果需要處理,則將此數(shù)據(jù)報(bào)進(jìn)行處理,否則,什么也不做。按照以上步驟,就完成了一個(gè)消息從消息生產(chǎn)者發(fā)送到事件通知服務(wù),再從事件通知服務(wù)發(fā)送到消息訂閱者的過程。本發(fā)明有益的效果是基于Java的IO和NIO的混合使用,將NIO用在服務(wù)端可以以非阻塞的形式處理連入socket,減少線程數(shù)量,從而減少資源的消耗,在客戶端利用老式IO與服務(wù)端連接,進(jìn)而大大提高了消息發(fā)送的速度,改進(jìn)了整個(gè)系統(tǒng)的性能。對(duì)于大規(guī)模分布式系統(tǒng)有著重要的意義。圖1為發(fā)布/訂閱系統(tǒng)的概念結(jié)構(gòu)示意圖。圖2為本發(fā)明的傳輸協(xié)議的整體流程圖。附圖標(biāo)記在第五步之前,我們應(yīng)該確定用戶名,并且檢査連接;④接受線程;⑩服務(wù)端發(fā)報(bào)機(jī);^客戶端發(fā)報(bào)機(jī);[M1讀寫線程^^客戶端處理器;A連接代理;O解碼器;^^服務(wù)端處理器;§數(shù)據(jù)報(bào)對(duì)列口客戶端連接代理;0客戶端讀線程;|SDS|服務(wù)端發(fā)報(bào)服務(wù);O客戶端發(fā)報(bào)服務(wù)。具體實(shí)施例方式下面結(jié)合附圖和實(shí)施例對(duì)本發(fā)明作進(jìn)一步介紹圖1中,Client2和CUent3為消息訂閱者,兩個(gè)客戶端向事件通知服務(wù)訂閱消息,而Clientl為消息發(fā)布者,負(fù)責(zé)向事件通知服務(wù)發(fā)送消息,當(dāng)事件通知服務(wù)接收到消息時(shí),就會(huì)向消息訂閱者發(fā)送其訂閱的消息。此時(shí)的消息訂閱者和消息發(fā)布者統(tǒng)稱為客戶端,而事件通知服務(wù)即為服務(wù)端。如圖2所示,整個(gè)系統(tǒng)由客戶端和服務(wù)端組成,并啟動(dòng)客戶端和服務(wù)端各自的操作來完成對(duì)消息的整個(gè)傳輸過程。上述各部分具體功能如下-接收線程服務(wù)器端監(jiān)視線程,接收客戶端連接,并把其注冊(cè)到相應(yīng)的讀寫線程上服務(wù)端發(fā)報(bào)機(jī)調(diào)用連接向服務(wù)器端發(fā)送數(shù)據(jù)報(bào)??蛻舳税l(fā)報(bào)機(jī)向客戶端發(fā)送數(shù)據(jù)報(bào)。讀寫線程服務(wù)端線程,調(diào)用連接代理讀取客戶端數(shù)據(jù)并將數(shù)據(jù)寫回客戶端??蛻舳颂幚砥魈幚矸?wù)器端返回?cái)?shù)據(jù)報(bào)。連接代理負(fù)責(zé)向客戶端寫入數(shù)據(jù)報(bào),并讀取數(shù)據(jù)報(bào)。解碼器將二進(jìn)制流轉(zhuǎn)換為數(shù)據(jù)報(bào),以及將數(shù)據(jù)報(bào)轉(zhuǎn)換為二進(jìn)制流。服務(wù)端處理器在服務(wù)器端處理從客戶端接收到的數(shù)據(jù)報(bào)。數(shù)據(jù)報(bào)隊(duì)列存儲(chǔ)數(shù)據(jù)報(bào)??蛻舳诉B接代理負(fù)責(zé)向客戶端寫入數(shù)據(jù)報(bào),并讀取數(shù)據(jù)報(bào)??蛻舳俗x線程讀取服務(wù)端發(fā)送的數(shù)據(jù)報(bào)。服務(wù)端發(fā)報(bào)服務(wù)啟動(dòng)服務(wù)端服務(wù),等待客戶端連接。客戶端發(fā)報(bào)服務(wù)啟動(dòng)客戶端服務(wù),與服務(wù)端建立連接,開始通訊。整個(gè)過程可描述如下首先啟動(dòng)服務(wù)端服務(wù),這個(gè)過程分為2個(gè)主要的步驟1、啟動(dòng)接收SocketChannel連接的接收線程(圖中接收線程);2、啟動(dòng)處理"讀""寫"任務(wù)的讀寫線程(圖中讀寫線程);在步驟1中,服務(wù)器的啟動(dòng)可以根據(jù)設(shè)定參數(shù)來確定同時(shí)啟動(dòng)讀寫線程數(shù)目,并只啟動(dòng)一個(gè)接收線程來接收客戶端的連接。其中讀寫線程里維持一個(gè)鏈表,用來存放接收到的客戶端連接。當(dāng)服務(wù)端啟動(dòng)以后,服務(wù)端就會(huì)有一個(gè)接收線程監(jiān)聽來自客戶端的socket連接,一旦有來自客戶端的socket連接,則讀、寫線程就會(huì)開始工作,即通過channel讀取socket中數(shù)據(jù)并將數(shù)據(jù)寫入soclcet。然后就開始創(chuàng)建客戶端到服務(wù)端的連接,這個(gè)過程分為5個(gè)主要的步驟1、用戶使用通過JNDI査找到的連接工廠來創(chuàng)建連接;2、根據(jù)査找到的連接類型從服務(wù)端發(fā)報(bào)機(jī)工廠中獲得相應(yīng)的服務(wù)端發(fā)報(bào)機(jī)(如圖);3、調(diào)用服務(wù)端發(fā)報(bào)機(jī)的方法,從客戶端打開一個(gè)Socket連接到服務(wù)器端;4、服務(wù)器端的接收線程接收連接,并把接收到的SocketChannel向服務(wù)器端的讀寫線程注冊(cè);5、啟動(dòng)客戶端的通訊層服務(wù),并客戶端讀線程(如圖)。在步驟1中,連接工程主要的功能為建立與服務(wù)器端的連接,當(dāng)連接建立好后,才可以發(fā)送、接收消息,其中連接可根據(jù)配置文件從連接工廠中創(chuàng)建。在步驟2中,連接類型可從配置文件中得到,而服務(wù)端發(fā)報(bào)機(jī)工廠為一創(chuàng)建發(fā)報(bào)機(jī)的對(duì)象,發(fā)報(bào)機(jī)則用來向服務(wù)端發(fā)送消息。在步驟3中,我們給服務(wù)端發(fā)報(bào)機(jī)定義了發(fā)送數(shù)據(jù)報(bào)的方法,利用socket定義的接口write()來發(fā)送各種數(shù)據(jù)報(bào)。在發(fā)送之前,這些數(shù)據(jù)報(bào)都經(jīng)過了加碼處理,變?yōu)槎M(jìn)制流發(fā)送到服務(wù)器端。在步驟4中,服務(wù)器端的接收線程不停査詢看是否有新的連接,如果有新的連接,則將此連接加入讀寫線程的鏈表中,并喚醒讀寫線程來處理鏈表的連接。步驟5中的通訊層服務(wù)啟動(dòng)后才可以讀取從服務(wù)器端發(fā)回的消息,讀線程主要用來讀取從服務(wù)端發(fā)回的數(shù)據(jù),并交給解碼器(如圖)處理。當(dāng)客戶端與服務(wù)端建立連接后,就開始消息的收發(fā)過程,此過程分為5個(gè)主要的步驟1、客戶端產(chǎn)生消息,把消息封裝成數(shù)據(jù)報(bào)中后,調(diào)用客戶端連接代理(如圖)來輸出數(shù)據(jù)報(bào);2、連接代理把數(shù)據(jù)報(bào)發(fā)往服務(wù)器端;3、服務(wù)器端的讀寫線程從Socket中讀到數(shù)據(jù),把數(shù)據(jù)提交給解碼器解碼;4、解碼器解碼得到數(shù)據(jù)報(bào)之后,判斷這個(gè)數(shù)據(jù)報(bào)是否需要提交給服務(wù)器端的處理器處理,如果不需要,什么都不做。如果需要,則服務(wù)端的處理器會(huì)調(diào)用相應(yīng)的方法來處理這個(gè)數(shù)據(jù)報(bào)。5、處理完這個(gè)數(shù)據(jù)報(bào)之后,通過連接代理把數(shù)據(jù)報(bào)的回執(zhí)發(fā)往客戶端。步驟1中產(chǎn)生消息主要是根據(jù)SUN公司制定的JMS規(guī)范中提供的的API(標(biāo)準(zhǔn)用戶接口)生產(chǎn)的,根據(jù)JMS規(guī)范,在生成消息的時(shí)候,可以給消息設(shè)置屬性。生成消息后,根據(jù)前面提到的加碼方法,將本消息封裝為一個(gè)數(shù)據(jù)報(bào)。步驟2中的發(fā)送方式主要為調(diào)用socket中的標(biāo)準(zhǔn)write0函數(shù)。步驟3中的讀寫線程讀取二進(jìn)制數(shù)據(jù),并將此二進(jìn)制數(shù)據(jù)交給解碼器解碼,將二進(jìn)制文件還原為一個(gè)標(biāo)準(zhǔn)的數(shù)據(jù)報(bào)。步驟4中,數(shù)據(jù)報(bào)可分為多種類型,有的數(shù)據(jù)報(bào)中封裝消息,有的數(shù)據(jù)報(bào)中封裝請(qǐng)求。而服務(wù)器端的根據(jù)不同的數(shù)據(jù)報(bào)類型會(huì)有不同的處理方式,比如有的數(shù)據(jù)報(bào)需要需要提取出消息后將消息存儲(chǔ)到數(shù)據(jù)庫中。步驟5中,連接代理會(huì)調(diào)用解碼器將數(shù)據(jù)報(bào)回執(zhí)解碼為二進(jìn)制數(shù)據(jù),通過前面提到的SelectableChannel的write()方法發(fā)往客戶端。當(dāng)服務(wù)端發(fā)送數(shù)據(jù)報(bào)后,客戶端會(huì)接收服務(wù)端發(fā)來的數(shù)據(jù),并進(jìn)行處理1、客戶端端的讀線程從Socket中讀到數(shù)據(jù),把數(shù)據(jù)提交給解碼器解碼;2、解碼器解碼得到數(shù)據(jù)報(bào)之后,判斷這個(gè)數(shù)據(jù)報(bào)是否需要提交給客戶端的處理器處理,如果不需要,則什么也不做。如果需要,則客戶端的處理器會(huì)調(diào)用相應(yīng)的方法來處理這個(gè)數(shù)據(jù)報(bào)。步驟1中,客戶端通過socket讀取一段二進(jìn)制數(shù)據(jù),并根據(jù)解碼器將此二進(jìn)制數(shù)據(jù)解為相應(yīng)的數(shù)據(jù)報(bào)。步驟2中,根據(jù)數(shù)據(jù)報(bào)類型進(jìn)行處理的時(shí)候,根據(jù)數(shù)據(jù)報(bào)類型的不同采取不同的處理方式。例如-.如果數(shù)據(jù)報(bào)中包含有消息,則將此消息提取出來。這樣,就完成了一個(gè)消息從消息發(fā)布者發(fā)送到事件通知服務(wù),再從事件通知服務(wù)發(fā)送到消息訂閱者的過程。上述實(shí)施例用來解釋說明本發(fā)明,而不是對(duì)本發(fā)明進(jìn)行限制,在本發(fā)明的精神和權(quán)利要求的保護(hù)范圍內(nèi),對(duì)本發(fā)明作出的任何修改和改變,都落入本發(fā)明的保護(hù)范圍。權(quán)利要求1、一種基于NIO和IO的面向發(fā)布訂閱系統(tǒng)的傳輸方法,其特征在于在服務(wù)端采用了JDK1.4中的NIO,啟用唯一的接收socket連接的線程,這個(gè)接收線程包含有一個(gè)Selector對(duì)象和一個(gè)讀線程組和寫線程組,Selector對(duì)象主要從客戶端捕捉到各種事件,讀線程組和寫線程組用來接收來自客戶端的socket連接以及向客戶端寫入數(shù)據(jù),這個(gè)Selector對(duì)象注冊(cè)了一個(gè)ServerSocketChannel對(duì)象,這個(gè)ServerSocketChannel對(duì)象用來接收來自客戶端的socket連接;每個(gè)讀線程或?qū)懢€程分別對(duì)應(yīng)一個(gè)socket連接,并將每次接收到的socket都封裝起來成為一個(gè)可讀寫數(shù)據(jù)的SelectableChannel對(duì)象,調(diào)用java的regist()函數(shù)將其再注冊(cè)到唯一的Selector對(duì)象上,當(dāng)客戶端連接關(guān)閉的時(shí)候,將連接從讀寫線程中注銷,注銷后,讀寫線程則可以綁定新的連接;對(duì)于選中的用來讀寫數(shù)據(jù)的Channel,包括ReadableByteChannel和WritableByteChannel進(jìn)行的操作是非阻塞的;在客戶端采用基于流的IO操作,按照以上步驟,就完成了一個(gè)消息從消息生產(chǎn)者發(fā)送到事件通知服務(wù),再從事件通知服務(wù)發(fā)送到消息訂閱者的過程。2、根據(jù)權(quán)利要求1所述的基于NIO和IO的面向發(fā)布訂閱系統(tǒng)的傳輸方法,其特征在于在客戶端采用基于流的IO操作,主要過程包括如下步驟1)啟動(dòng)服務(wù)器端接收SocketChannel連接的接收線程,并啟動(dòng)讀、寫線程組;2)客戶端進(jìn)行操作時(shí),打開一個(gè)Socket連接到服務(wù)器端,服務(wù)器端的接收線程開始接收連接,并把接收到的SocketChannel向服務(wù)器端的讀寫線程注冊(cè),即將連接的SocketChannel綁定到讀寫線程上;3)客戶端將要發(fā)送的消息作為數(shù)據(jù)報(bào)的一部分,每個(gè)數(shù)據(jù)報(bào)格式為數(shù)據(jù)報(bào)頭、消息體,其中數(shù)據(jù)報(bào)頭包含一個(gè)特殊的標(biāo)志符和表示消息大小的一個(gè)整數(shù),而后將數(shù)據(jù)報(bào)加碼為二進(jìn)制流,然后通過Socket調(diào)用write()函數(shù)將數(shù)據(jù)報(bào)發(fā)送到服務(wù)器端;4)服務(wù)器端讀線程從Socket中讀取標(biāo)志數(shù)據(jù)報(bào)的二進(jìn)制流,如讀取數(shù)據(jù)為數(shù)據(jù)報(bào)頭,則新建一個(gè)數(shù)據(jù)報(bào),并將此流解碼為數(shù)據(jù)報(bào);然后服務(wù)器處理此數(shù)據(jù)報(bào),并生成返回客戶端的數(shù)據(jù)報(bào),利用NIO的WriteableByteChaimel,將處理后得到的數(shù)據(jù)報(bào)加碼后變?yōu)槎M(jìn)制流,發(fā)送到客戶端;5)客戶端從Socket讀取此二進(jìn)制流,同上解碼為數(shù)據(jù)報(bào),并根據(jù)數(shù)據(jù)報(bào)格式判斷數(shù)據(jù)報(bào)是否需要客戶端處理器進(jìn)行處理,如果需要處理,則將此數(shù)據(jù)報(bào)進(jìn)行處理,否則,什么也不做。全文摘要本發(fā)明涉及一種基于NIO和IO的面向發(fā)布訂閱系統(tǒng)的傳輸方法,在服務(wù)端采用NIO,啟用唯一的接收socket連接的線程,這個(gè)接收線程包含有Selector對(duì)象、讀線程組和寫線程組,Selector對(duì)象從客戶端捕捉到各種事件,讀線程組和寫線程組用來接收來自客戶端的socket連接以及向客戶端寫入數(shù)據(jù);每個(gè)讀線程或?qū)懢€程分別對(duì)應(yīng)一個(gè)socket連接,并將每次接收到的socket都封裝起來成為一個(gè)可讀寫數(shù)據(jù)的對(duì)象,將其再注冊(cè)到唯一的Selector對(duì)象上,當(dāng)客戶端連接關(guān)閉的時(shí),將連接從讀寫線程中注銷,注銷后,讀寫線程則可以綁定新的連接。本發(fā)明優(yōu)點(diǎn)是基于java的IO和NIO的混合使用,將NIO用在服務(wù)端減少線程數(shù)量,從而減少資源的消耗,在客戶端利用IO與服務(wù)端連接,進(jìn)而大大提高了消息發(fā)送的速度。文檔編號(hào)H04L29/08GK101651698SQ20071016475公開日2010年2月17日申請(qǐng)日期2007年12月12日優(yōu)先權(quán)日2007年12月12日發(fā)明者健吳,吳朝暉,尹建偉,施東材,瑩李,楨王,鄧水光申請(qǐng)人:浙江大學(xué)