1. 程式人生 > >Java NIO框架Netty教程(三) 字符串消息收發

Java NIO框架Netty教程(三) 字符串消息收發

view itl col ioc 啟動 type lines nta tty

了解了Netty的基本概念(http://www.it165.net/pro/html/201207/3173.html),開發起來應該會順手很多。 在“Hello World(http://www.it165.net/pro/html/201207/3142.html)”代碼中,我們只是在完成綁定的時候,在各自的本地打印了簡單的信息,並沒有客戶端和服務端的消息傳遞。這個肯定是最基本的功能。在上代碼之前,先補充一個Netty中重要的概念,ChannelBuffer.


ChannelBuffer

技術分享

Netty中的消息傳遞,都必須以字節的形式,以ChannelBuffer為載體傳遞。簡單的說,就是你想直接寫個字符串過去,對不起,拋異常。雖然,Netty定義的writer的接口參數是Object的,這可能也是會給新上手的朋友容易造成誤會的地方。Netty源碼中,是這樣判斷的:

view sourceprint? 01.SendBuffer acquire(Object message) { 02.if (message instanceof ChannelBuffer) { 03.return acquire((ChannelBuffer) message); 04.} else if (message instanceof FileRegion) { 05.return acquire((FileRegion) message); 06.} 07. 08.throw new IllegalArgumentException( 09."unsupported message type: "
+ message.getClass());
10.}

所以,我們要想傳遞字符串,那麽就必須轉換成ChannelBuffer。明確了這一點,接下來我們上代碼:

view sourceprint? 01./** 02.* @author lihzh 03.* @alia OneCoder 04.* @blog http://www.coderli.com 05.*/ 06.public class MessageServer { 07. 08.public static void main(String args[]) { 09.// Server服務啟動器 10.ServerBootstrap bootstrap =
new ServerBootstrap(
11.new NioServerSocketChannelFactory( 12.Executors.newCachedThreadPool(), 13.Executors.newCachedThreadPool())); 14.// 設置一個處理客戶端消息和各種消息事件的類(Handler) 15.bootstrap.setPipelineFactory(new ChannelPipelineFactory() { 16.@Override 17.public ChannelPipeline getPipeline() throws Exception { 18.return Channels.pipeline(new MessageServerHandler()); 19.} 20.}); 21.// 開放8000端口供客戶端訪問。 22.bootstrap.bind(new InetSocketAddress(8000)); 23.} 24. 25.private static class MessageServerHandler extends SimpleChannelHandler { 26. 27./** 28.* 用戶接受客戶端發來的消息,在有客戶端消息到達時觸發 29.* 30.* @author lihzh 31.* @alia OneCoder 32.*/ 33.@Override 34.public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { 35.ChannelBuffer buffer = (ChannelBuffer) e.getMessage(); 36.System.out.println(buffer.toString(Charset.defaultCharset())); 37.} 38. 39.} 40.} 41./** 42.* @author lihzh 43.* @alia OneCoder 44.* @blog http://www.coderli.com 45.*/ 46.public class MessageClient { 47. 48.public static void main(String args[]) { 49.// Client服務啟動器 50.ClientBootstrap bootstrap = new ClientBootstrap( 51.new NioClientSocketChannelFactory( 52.Executors.newCachedThreadPool(), 53.Executors.newCachedThreadPool())); 54.// 設置一個處理服務端消息和各種消息事件的類(Handler) 55.bootstrap.setPipelineFactory(new ChannelPipelineFactory() { 56.@Override 57.public ChannelPipeline getPipeline() throws Exception { 58.return Channels.pipeline(new MessageClientHandler()); 59.} 60.}); 61.// 連接到本地的8000端口的服務端 62.bootstrap.connect(new InetSocketAddress("127.0.0.1", 8000)); 63.} 64. 65.private static class MessageClientHandler extends SimpleChannelHandler { 66. 67./** 68.* 當綁定到服務端的時候觸發,給服務端發消息。 69.* 70.* @alia OneCoder 71.* @author lihzh 72.*/ 73.@Override 74.public void channelConnected(ChannelHandlerContext ctx, 75.ChannelStateEvent e) { 76.// 將字符串,構造成ChannelBuffer,傳遞給服務端 77.String msg = "Hello, I‘m client."; 78.ChannelBuffer buffer = ChannelBuffers.buffer(msg.length()); 79.buffer.writeBytes(msg.getBytes()); 80.e.getChannel().write(buffer); 81.} 82.} 83. 84.}

與 “Hello World(http://www.it165.net/pro/html/201207/3142.html)” 樣例代碼不同的是,客戶端在channel連通後,不是在本地打印,而是將消息轉換成ChannelBuffer傳遞給服務端,服務端接受到ChannelBuffer後,解碼成字符串打印出來。


同時,通過對比可以發現,變動的只是Handler裏的代碼,啟動服務和綁定服務的代碼沒有變化,也就是我們在概念介紹裏提到了,關註Handler,在Handler裏處理我們自己的業務。所以,以後我們會只給出業務中關鍵代碼,不會在上重復的代碼:)

由於在Netty中消息的收發全依賴於ChannelBuffer,所以,下一章我們將會詳細的介紹ChannelBuffer的使用。我們一起學習。

Java NIO框架Netty教程(三) 字符串消息收發