事件管道模型
很多人知道事件驅動(dòng)模式,那么事件管道(Event Pipeline)模式是什么?下面我們一起來(lái)探討
event 的出現是設計為一個(gè)對象的狀態(tài)的改變即就通知對該對象感興趣的其他對象。
一般產(chǎn)生一個(gè)event總是有個(gè)發(fā)源地,我們可以把這個(gè)發(fā)源地叫做Event Generators而在java的EventObject interface中其實(shí)應該就是指的
source參數。
通常我們事件驅動(dòng)模式是在一個(gè)本機上做,其實(shí)這個(gè)模式在分布式環(huán)境中也可以采用事件驅動(dòng)模式。從整個(gè)模式上看,本地的事件驅動(dòng)模型(local event)
和遠程的事件驅動(dòng)模型(remote event)沒(méi)有什么本質(zhì)區別,但有幾點(diǎn)需要注意
1.local event:所有的對象都在本地包括需要通知的對象。
remote event:Event Generators在一段,remote event 有Event Generators產(chǎn)生后通知另外遠端的entity。
2.因為有遠端那么就涉及到網(wǎng)絡(luò )通信,因此通常不能保證網(wǎng)絡(luò )通信一直通暢,所有remote event的模式可能或出現event丟失不能達到對方的情況。
3.local event 在本地,所以往往event很快,相應的處理的反饋也快,因此你會(huì )發(fā)現本地的event模式通常都類(lèi)似于http的握手模式,也就是一個(gè)event觸發(fā)
通常就直接通知給所有監聽(tīng)器。
而remote event 是遠程event的傳送,那么在網(wǎng)絡(luò )通信其實(shí)消耗大量的時(shí)間,那么我認為client端多event的發(fā)送,server端統一處理一批event可能是節省資源
比較好的方式。
因此我們這里引入Event Pipeline,他是對server端接收到的event進(jìn)行管理,將event 放入管道進(jìn)行各自策略的處理。
另外我們把遠端的Event Listener叫做Remote Event Listener,其實(shí)本質(zhì)是一樣的,只是為了區分。
當許多remote events 在同一個(gè)管道的時(shí)候,那么我們需要根據不同的需要來(lái)定制event的策略,下面列舉以下一些策略
a.In-order delivery
events按照某種順序傳遞
b. Efficient delivery
多個(gè)event 合并為一個(gè)event
c. Store and forward
event 暫停在管道中,等待某個(gè)條件出現再繼續傳遞
d. Filtering of events
根據條件過(guò)濾相應event
e. Grouping of events
多個(gè)event 被一個(gè)event代替
PipeLine 流程:
Event Generator ---> Event pipeLine -->Event Consumer
其中pipeLine中可以動(dòng)態(tài)地設置一個(gè)或者多個(gè)策略。
posted @ 2010-12-01 16:46 linugb118 閱讀(1323) | 評論 (0) | 編輯 收藏
Netty Channel 接口名詞理解
1.Channel
channel 是負責數據讀,寫(xiě)的對象,有點(diǎn)類(lèi)似于老的io里面的stream,他和stream的區別,channel是雙向的
既可以write 也可以read,而stream要分outstream和inputstream。而且在NIO中用戶(hù)不應該直接從channel中讀寫(xiě)數據,
而是應該通過(guò)buffer,通過(guò)buffer再將數據讀寫(xiě)到channel中。
一個(gè)channel 可以提供給用戶(hù)下面幾個(gè)信息
(1)channel的當前狀態(tài),比如open 還是closed
(2)ChannelConfig對象,表示channel的一些參數,比如bufferSize
(3)channel支持的所有i/o操作(比如read,write,connect.bind)以及ChannelPipeLine(下面解釋?zhuān)?
2.ChannelConfig
channel的參數,以Map 數據結構來(lái)存儲
3.ChannelEvent
ChannelEvent廣義的認為Channel相關(guān)的事件,他是否分Upstream events和downstream events兩大塊,這里需要注意的,讓是server為
主體的話(huà),從client的數據到server的過(guò)程是Upstream;而server到client的數據傳輸過(guò)程叫downstream;而如果以client為主體
的話(huà),從server到client的過(guò)程對client來(lái)說(shuō)是Upstream,而client到server的過(guò)程對client來(lái)說(shuō)就是downstream。
Upstream events包括:
messageReceived:信息被接受時(shí) ---MessageEvent
exceptionCaught:產(chǎn)生異常時(shí) ---ExceptionEvent
channelOpen:channel被開(kāi)啟時(shí) ---ChannelStateEvent
channelClosed:channel被關(guān)閉時(shí) ---ChannelStateEvent
channelBound:channel被開(kāi)啟并準備去連接但還未連接上的時(shí)候 ---ChannelStateEvent
channelUnbound:channel被開(kāi)啟不準備去連接時(shí)候 ---ChannelStateEvent
channelConnected:channel被連接上的時(shí)候 ---ChannelStateEvent
channelDisconnected:channel連接斷開(kāi)的時(shí)候 ---ChannelStateEvent
channelInterestChanged:Channel的interestOps被改變的時(shí)候 ------ChannelStateEvent
writeComplete:寫(xiě)到遠程端完成的時(shí)候 --WriteCompletionEvent
Downstream events包括:
write:發(fā)送信息給channel的時(shí)候 --MessageEvent
bind:綁定一個(gè)channel到指定的本地地址 --ChannelStateEvent
unbind:解除當前本地端口的綁定--ChannelStateEvent
connect:將channel連接到遠程的機 --ChannelStateEvent
disconnect:將channel與遠程的機連接斷開(kāi) --ChannelStateEvent
close:關(guān)閉channel --ChannelStateEvent
需要注意的是,這里沒(méi)有open event,這是因為當一個(gè)channel被channelFactory創(chuàng )建的話(huà),channel總是已經(jīng)被打開(kāi)了。
此外還有兩個(gè)事件類(lèi)型是當父channel存在子channel的情況
childChannelOpen:子channel被打開(kāi) ---ChannelStateEvent
childChannelClosed:子channel被關(guān)閉 ---ChannelStateEvent
4.ChannelHandler
channel是負責傳送數據的載體,那么數據肯定需要根據要求進(jìn)行加工處理,那么這個(gè)時(shí)候就用到ChannelHandler
不同的加工可以構建不同的ChannelHandler,然后放入ChannelPipeline中
此外需要有ChannelEvent觸發(fā)后才能到達ChannelHandler,因此根據event不同有下面兩種的sub接口ChannelUpstreamHandler
和ChannelDownstreamHandler。
一個(gè)ChannelHandler通常需要存儲一些狀態(tài)信息作為判斷信息,常用做法定義一個(gè)變量
比如
public class DataServerHandler extends {@link SimpleChannelHandler} {
*
* <b>private boolean loggedIn;</b>
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* {@link Channel} ch = e.getChannel();
* Object o = e.getMessage();
* if (o instanceof LoginMessage) {
* authenticate((LoginMessage) o);
* <b>loggedIn = true;</b>
* } else (o instanceof GetDataMessage) {
* if (<b>loggedIn</b>) {
* ch.write(fetchSecret((GetDataMessage) o));
* } else {
* fail();
* }
* }
* }
* ...
* }
// Create a new handler instance per channel.
* // See {@link Bootstrap#setPipelineFactory(ChannelPipelineFactory)}.
* public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
* public {@link ChannelPipeline} getPipeline() {
* return {@link Channels}.pipeline(<b>new DataServerHandler()</b>);
* }
* }
除了這種,每個(gè)ChannelHandler都可以從ChannelHandlerContext中獲取或設置數據,那么下面的做法就是利用ChannelHandlerContext
設置變量
* {@code @Sharable}
* public class DataServerHandler extends {@link SimpleChannelHandler} {
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* {@link Channel} ch = e.getChannel();
* Object o = e.getMessage();
* if (o instanceof LoginMessage) {
* authenticate((LoginMessage) o);
* <b>ctx.setAttachment(true)</b>;
* } else (o instanceof GetDataMessage) {
* if (<b>Boolean.TRUE.equals(ctx.getAttachment())</b>) {
* ch.write(fetchSecret((GetDataMessage) o));
* } else {
* fail();
* }
* }
* }
* ...
* }
* public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
*
* private static final DataServerHandler <b>SHARED</b> = new DataServerHandler();
*
* public {@link ChannelPipeline} getPipeline() {
* return {@link Channels}.pipeline(<b>SHARED</b>);
* }
* }
這兩種做法還是有區別的,上面的變量做法,每個(gè)new的handler 對象,變量是不共享的,而下面的ChannelHandlerContext是共享的
如果需要不同的handler之間共享數據,那怎么辦,那就用ChannelLocal
例子:
public final class DataServerState {
*
* <b>public static final {@link ChannelLocal}<Boolean> loggedIn = new {@link ChannelLocal}<Boolean>() {
* protected Boolean initialValue(Channel channel) {
* return false;
* }
* }</b>
* ...
* }
*
* {@code @Sharable}
* public class DataServerHandler extends {@link SimpleChannelHandler} {
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* Channel ch = e.getChannel();
* Object o = e.getMessage();
* if (o instanceof LoginMessage) {
* authenticate((LoginMessage) o);
* <b>DataServerState.loggedIn.set(ch, true);</b>
* } else (o instanceof GetDataMessage) {
* if (<b>DataServerState.loggedIn.get(ch)</b>) {
* ctx.getChannel().write(fetchSecret((GetDataMessage) o));
* } else {
* fail();
* }
* }
* }
* ...
* }
*
* // Print the remote addresses of the authenticated clients:
* {@link ChannelGroup} allClientChannels = ...;
* for ({@link Channel} ch: allClientChannels) {
* if (<b>DataServerState.loggedIn.get(ch)</b>) {
* System.out.println(ch.getRemoteAddress());
* }
* }
* </pre>
5.ChannelPipeline
channelPipeline是一系列channelHandler的集合,他參照J2ee中的Intercepting Filter模式來(lái)實(shí)現的,
讓用戶(hù)完全掌握如果在一個(gè)handler中處理事件,同時(shí)讓pipeline里面的多個(gè)handler可以相互交互。
Intercepting Filter:http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html
對于每一個(gè)channel都需要有相應的channelPipeline,當為channel設置了channelPipeline后就不能再為channel重新設置
channelPipeline。此外建議的做法的通過(guò)Channels 這個(gè)幫助類(lèi)來(lái)生成ChannelPipeline 而不是自己去構建ChannelPipeline
通常pipeLine 添加多個(gè)handler,是基于業(yè)務(wù)邏輯的
比如下面
{@link ChannelPipeline} p = {@link Channels}.pipeline();
* p.addLast("1", new UpstreamHandlerA());
* p.addLast("2", new UpstreamHandlerB());
* p.addLast("3", new DownstreamHandlerA());
* p.addLast("4", new DownstreamHandlerB());
* p.addLast("5", new SimpleChannelHandler());
upstream event 執行的handler按順序應該是 125
downstream event 執行的handler按順序應該是 543
SimpleChannelHandler 是同時(shí)實(shí)現了 ChannelUpstreamHandler和ChannelDownstreamHandler的類(lèi)
上面只是具有邏輯,如果數據需要通過(guò)格式來(lái)進(jìn)行編碼的話(huà),那需要這些寫(xiě)
* {@link ChannelPipeline} pipeline = {@link Channels#pipeline() Channels.pipeline()};
* pipeline.addLast("decoder", new MyProtocolDecoder());
* pipeline.addLast("encoder", new MyProtocolEncoder());
* pipeline.addLast("executor", new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));
* pipeline.addLast("handler", new MyBusinessLogicHandler());
其中:
Protocol Decoder - 將binary轉換為java對象
Protocol Encoder - 將java對象轉換為binary
ExecutionHandler - applies a thread model.
Business Logic Handler - performs the actual business logic(e.g. database access)
雖然不能為channel重新設置channelPipeline,但是channelPipeline本身是thread-safe,因此你可以在任何時(shí)候為channelPipeline添加刪除channelHandler
需要注意的是,下面的代碼寫(xiě)法不能達到預期的效果
* public class FirstHandler extends {@link SimpleChannelUpstreamHandler} {
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* // Remove this handler from the pipeline,
* ctx.getPipeline().remove(this);
* // And let SecondHandler handle the current event.
* ctx.getPipeline().addLast("2nd", new SecondHandler());
* ctx.sendUpstream(e);
* }
* }
前提現在Pipeline只有最后一個(gè)FirstHandler,
上面明顯是想把FirstHandler從Pipeline中移除,然后添加SecondHandler。而pipeline需要只要有一個(gè)Handler,因此如果想到到達這個(gè)效果,那么可以
先添加SecondHandler,然后在移除FirstHandler。
6.ChannelFactory
channel的工廠(chǎng)類(lèi),也就是用來(lái)生成channel的類(lèi),ChannelFactory根據指定的通信和網(wǎng)絡(luò )來(lái)生成相應的channel,比如
NioServerSocketChannelFactory生成的channel是基于NIO server socket的。
當一個(gè)channel創(chuàng )建后,ChannelPipeline將作為參數附屬給該channel。
對于channelFactory的關(guān)閉,需要做兩步操作
第一,關(guān)閉所有該factory產(chǎn)生的channel包括子channel。通常調用ChannelGroup#close()。
第二,釋放channelFactory的資源,調用releaseExternalResources()
7.ChannelGroup
channel的組集合,他包含一個(gè)或多個(gè)open的channel,closed channel會(huì )自動(dòng)從group中移除,一個(gè)channel可以在一個(gè)或者多個(gè)channelGroup
如果想將一個(gè)消息廣播給多個(gè)channel,可以利用group來(lái)實(shí)現
比如:
{@link ChannelGroup} recipients = new {@link DefaultChannelGroup}()
recipients.add(channelA);
recipients.add(channelB);
recipients.write(ChannelBuffers.copiedBuffer("Service will shut down for maintenance in 5 minutes.",CharsetUtil.UTF_8));
當ServerChannel和非ServerChannel同時(shí)都在channelGroup中的時(shí)候,任何io請求的操作都是先在ServerChannel中執行再在其他Channel中執行。
這個(gè)規則對關(guān)閉一個(gè)server非常適用。
8.ChannelFuture
在netty中,所有的io傳輸都是異步,所有那么在傳送的時(shí)候需要數據+狀態(tài)來(lái)確定是否全部傳送成功,而這個(gè)載體就是ChannelFuture。
9.ChannelGroupFuture
針對一次ChannelGroup異步操作的結果,他和ChannelFuture一樣,包括數據和狀態(tài)。不同的是他由channelGroup里面channel的所有channelFuture
組成。
10.ChannelGroupFutureListener
針對ChannelGroupFuture的監聽(tīng)器,同樣建議使用ChannelGroupFutureListener而不是await();
11.ChannelFutureListener
ChannelFuture監聽(tīng)器,監聽(tīng)channelFuture的結果。
12.ChannelFutureProgressListener
監聽(tīng)ChannelFuture處理過(guò)程,比如一個(gè)大文件的傳送。而ChannelFutureListener只監聽(tīng)ChannelFuture完成未完成
13.ChannelHandlerContext
如何讓handler和他的pipeLine以及pipeLine中的其他handler交換,那么就要用到ChannelHandlerContext,
ChannelHandler可以通過(guò)ChannelHandlerContext的sendXXXstream(ChannelEvent)將event傳給最近的handler
可以通過(guò)ChannelHandlerContext的getPipeline來(lái)得到Pipeline,并修改他,ChannelHandlerContext還可以存放一下?tīng)顟B(tài)信息attments。
一個(gè)ChannelHandler實(shí)例可以有一個(gè)或者多個(gè)ChannelHandlerContext
14.ChannelPipelineFactory
產(chǎn)生ChannelPipe的工廠(chǎng)類(lèi)
15.ChannelState
記載channel狀態(tài)常量
posted @ 2010-11-12 15:36 linugb118 閱讀(1120) | 評論 (0) | 編輯 收藏
Netty 簡(jiǎn)單樣例分析
Netty 是JBoss旗下的io傳輸的框架,他利用java里面的nio來(lái)實(shí)現高效,穩定的io傳輸。
作為io傳輸,就會(huì )有client和server,下面我們看看用netty怎樣寫(xiě)client和server
Client:
需要做的事情:
1.配置client啟動(dòng)類(lèi)
ClientBootstrap bootstrap = new ClientBootstrap(..)
2.根據不同的協(xié)議或者模式為client啟動(dòng)類(lèi)設置pipelineFactory。
這里telnet pipline Factory 在netty中已經(jīng)存在,所有直接用
bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());
也可以自己定義
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new DiscardClientHandler(firstMessageSize));
}
});
這里DiscardClientHandler 就是自己定義的handler,他需要
public class DiscardServerHandler extends SimpleChannelUpstreamHandler
繼承SimpleChannelUpstreamHandler 來(lái)實(shí)現自己的handler。這里DiscardClientHandler
是處理自己的client端的channel,他的
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Server is supposed to send nothing. Therefore, do nothing.
}
可以看到Discard client不需要接受任何信息
3.連接server
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
這里解釋一下channelFuture:
在Netty中所有的io操作都是異步的,這也就是意味任何io訪(fǎng)問(wèn),那么就立即返回處理,并且不能確保
返回的數據全部完成。因此就出現了channelFuture,channelFuture在傳輸數據時(shí)候包括數據和狀態(tài)兩個(gè)
部分。他只有Uncompleted和Completed
既然netty io是異步的,那么如何知道channel傳送完成有兩種方式,一種添加監聽(tīng)器
addListener(ChannelFutureListener) 還有一種直接調用await()方法,這兩種方式
有下面的區別
監聽(tīng)器:是以事件模式的,因此代碼就需要用事件模式的樣式去寫(xiě),相當復雜,但他是non-blocking模式的
性能方面要比await方法好,而且不會(huì )產(chǎn)生死鎖情況
await(): 直接方法調用,使用簡(jiǎn)單,但是他是blocking模式,性能方面要弱而且會(huì )產(chǎn)生死鎖情況
不要在ChannelHandler 里面調用await(),這是因為通常在channelHandler里的event method是被i/o線(xiàn)程調用的
(除非ChannelPipeline里面有個(gè)ExecutionHandler),那么如果這個(gè)時(shí)候用await就容易產(chǎn)生死鎖。
錯誤樣例:
// BAD - NEVER DO THIS
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* if (e.getMessage() instanceof GoodByeMessage) {
* {@link ChannelFuture} future = e.getChannel().close();
* future.awaitUninterruptibly();
* // Perform post-closure operation
* // ...
* }
* }
*
正確樣例:
* // GOOD
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* if (e.getMessage() instanceof GoodByeMessage) {
* {@link ChannelFuture} future = e.getChannel().close();
* future.addListener(new {@link ChannelFutureListener}() {
* public void operationComplete({@link ChannelFuture} future) {
* // Perform post-closure operation
* // ...
* }
* });
* }
* }
雖然await調用比較危險,但是你確保不是在一個(gè)i/o 線(xiàn)程中調用該方法,畢竟await方法還是很簡(jiǎn)潔方便的,如果
調用該方法是在一個(gè)i/o 線(xiàn)程,那么就會(huì )拋出 IllegalStateException
await的timeout和i/o timeout區別
需要注意的是這兩個(gè)timeout是不一樣的, #await(long),#await(long, TimeUnit), #awaitUninterruptibly(long),
#awaitUninterruptibly(long, TimeUnit) 這里面的timeout也i/o timeout 沒(méi)有任何關(guān)系,如果io timeout,那么
channelFuture 將被標記為completed with failure,而await的timeout 與future完全沒(méi)有關(guān)系,只是await動(dòng)作的
timeout。
錯誤代碼
* // BAD - NEVER DO THIS
* {@link ClientBootstrap} b = ...;
* {@link ChannelFuture} f = b.connect(...);
* f.awaitUninterruptibly(10, TimeUnit.SECONDS);
* if (f.isCancelled()) {
* // Connection attempt cancelled by user
* } else if (!f.isSuccess()) {
* // You might get a NullPointerException here because the future
* // might not be completed yet.
* f.getCause().printStackTrace();
* } else {
* // Connection established successfully
* }
*
正確代碼
* // GOOD
* {@link ClientBootstrap} b = ...;
* // Configure the connect timeout option.
* <b>b.setOption("connectTimeoutMillis", 10000);</b>
* {@link ChannelFuture} f = b.connect(...);
* f.awaitUninterruptibly();
*
* // Now we are sure the future is completed.
* assert f.isDone();
*
* if (f.isCancelled()) {
* // Connection attempt cancelled by user
* } else if (!f.isSuccess()) {
* f.getCause().printStackTrace();
* } else {
* // Connection established successfully
* }
4.等待或監聽(tīng)數據全部完成
如: future.getChannel().getCloseFuture().awaitUninterruptibly();
5.釋放連接等資源
bootstrap.releaseExternalResources();
Server:
1.配置server
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
2.設置pipeFactory
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new EchoServerHandler());
}
});
或者
bootstrap.setPipelineFactory(new HttpServerPipelineFactory());
3.綁定sever端端口
bootstrap.bind(new InetSocketAddress(8080));
posted @ 2010-11-11 14:03 linugb118 閱讀(902) | 評論 (1) | 編輯 收藏
Netty 源碼研究
org.jboss.netty.bootstrap
本身 Netty 可以作為一個(gè)server存在的,因此他存在啟動(dòng)入口,他具有client啟動(dòng),server啟動(dòng)以及connectionless 啟動(dòng)(比如UDP)
1.基類(lèi)bootstrap:他包含ChannelFactory,ChannelPipeline,ChannelPipelineFactory。
ClientBootstrap: 有connect()方法
ConnectionlessBootstrap:有connect(),bind()方法
ServerBootstrap:有bind()方法
2.org.jboss.netty.buffer
netty自己提供了buffer 來(lái)取代nio 中的java.nio.ByteBuffer,他與nio中的byteBuffer相比,有下面的幾個(gè)特點(diǎn)
1>可以根據自己需要自己定義buffer type
2>只是buffer type改變而不拷貝buffer的內容,這樣可以減少開(kāi)銷(xiāo)
3>動(dòng)態(tài)大小的buffer type 類(lèi)似于stringbuffer
4>不需要調用flip()方法
5>更快的性能
3.org.jboss.netty.channel
channel的核心api,包括異步和事件驅動(dòng)等各種傳送接口
org.jboss.netty.channel.group
channel group,里面包含一系列open的channel
org.jboss.netty.channel.local
一種虛擬的運輸方式,能允許同一個(gè)虛擬機上的兩個(gè)部分可以互相通信
org.jboss.netty.channel.socket
TCP,UDP端口接口,主要繼承channel
org.jboss.netty.channel.socket.nio
基于nio端口channel的具體實(shí)現
org.jboss.netty.channel.socket.oio
基于老的io端口的channel的具體實(shí)現
org.jboss.netty.channel.socket.http
基于http的客戶(hù)端和相應的server端的實(shí)現,可以在有防火墻的情況下進(jìn)行工作
需要做的事情
a. 將http tunnel 作為servlet進(jìn)行配置
web.xml
<servlet>
* <servlet-name>NettyTunnelingServlet</servlet-name>
* <servlet-class>org.jboss.netty.channel.socket.http.HttpTunnelingServlet</servlet-class>
* <!--
* The name of the channel, this should be a registered local channel.
* See LocalTransportRegister.
* -->
* <init-param>
* <param-name>endpoint</param-name>
* <param-value>local:myLocalServer</param-value>
* </init-param>
* <load-on-startup>1</load-on-startup>
* </servlet>
*
* <servlet-mapping>
* <servlet-name>NettyTunnelingServlet</servlet-name>
* <url-pattern>/netty-tunnel</url-pattern>
* </servlet-mapping>
接下來(lái)需要將你的基于netty的server app綁定到上面的http servlet
你可以這樣寫(xiě)
*
* public class LocalEchoServerRegistration {
*
* private final ChannelFactory factory = new DefaultLocalServerChannelFactory();
* private volatile Channel serverChannel;
*
* public void start() {
* ServerBootstrap serverBootstrap = new ServerBootstrap(factory);
* EchoHandler handler = new EchoHandler();
* serverBootstrap.getPipeline().addLast("handler", handler);
*
* // Note that "myLocalServer" is the endpoint which was specified in web.xml.
* serverChannel = serverBootstrap.bind(new LocalAddress("myLocalServer"));
* }
*
* public void stop() {
* serverChannel.close();
* }
* }
然后在Ioc framework(JBoss Microcontainer,Guice,Spring)中定義bean
<bean name="my-local-echo-server"
class="org.jboss.netty.example.http.tunnel.LocalEchoServerRegistration" />
這樣http servlet 就可以了
b. 連接http tunnel
構造client
* ClientBootstrap b = new ClientBootstrap(
* new HttpTunnelingClientSocketChannelFactory(
* new NioClientSocketChannelFactory(...)));
*
* // Configure the pipeline (or pipeline factory) here.
* ...
*
* // The host name of the HTTP server
* b.setOption("serverName", "example.com");
* // The path to the HTTP tunneling Servlet, which was specified in in web.xml
* b.setOption("serverPath", "contextPath/netty-tunnel");
* b.connect(new InetSocketAddress("example.com", 80);
4.org.jboss.netty.container
各種容器的兼容
org.jboss.netty.container.microcontainer
JBoss Microcontainer 整合接口
org.jboss.netty.container.osgi
OSGi framework 整合接口
org.jboss.netty.container.spring
Spring framework 整合接口
5.org.jboss.netty.handler
處理器
org.jboss.netty.handler.codec.base64
Base64 編碼
org.jboss.netty.handler.codec.compression
壓縮格式
org.jboss.netty.handler.codec.embedder
嵌入模式下編碼和解碼,即使沒(méi)有真正的io環(huán)境也能使用
org.jboss.netty.handler.codec.frame
可擴展的接口,重新評估基于流的數據的排列和內容
org.jboss.netty.handler.codec.http.websocket
websocket相關(guān)的編碼和解碼,
參考
http://en.wikipedia.org/wiki/Web_Sockets
org.jboss.netty.handler.codec.http
http的編碼解碼以及類(lèi)型信息
org.jboss.netty.handler.codec.oneone
一個(gè)對象到另一對象的自定義抽象接口,如果有自己編碼需要繼承該抽象類(lèi)
org.jboss.netty.handler.codec.protobuf
Google Protocol Buffers的編碼解碼
Google Protocol Buffers參考下面
http://code.google.com/p/protobuf/
org.jboss.netty.handler.codec.replay
org.jboss.netty.handler.codec.rtsp
Real_Time_Streaming_Protocol的編碼解碼
Real_Time_Streaming_Protocol 參考下面wiki
http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol
org.jboss.netty.handler.codec.serialization
將序列化的對象轉換到byte buffer的相關(guān)實(shí)現
org.jboss.netty.handler.codec.string
字符串編碼解碼,比如utf8編碼等,繼承oneone包的接口
org.jboss.netty.handler.execution
基于java.util.concurrent.Executor的實(shí)現
org.jboss.netty.handler.queue
將event存入內部隊列的處理
org.jboss.netty.handler.ssl
基于javax.net.ssl.SSLEngine的SSL以及TLS實(shí)現
參考
http://en.wikipedia.org/wiki/Transport_Layer_Security
org.jboss.netty.handler.stream
異步寫(xiě)入大數據,不會(huì )產(chǎn)生outOfMemory 也不會(huì )花費很多內存
org.jboss.netty.handler.timeout
通過(guò)jboss.netty.util.Timer來(lái)對讀寫(xiě)超時(shí)或者閑置鏈接的通知
6.org.jboss.netty.logging
根據不同的log framework 實(shí)現的類(lèi)
7.org.jboss.netty.util
nettyutil類(lèi)
org.jboss.netty.util.internal
netty內部util類(lèi),不被外部使用
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。