標籤:socket col har one except .com reg bootstrap text
瞭解了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 lihzh03.* @alia OneCoder04.* @blog http://www.coderli.com05.*/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.@Override17.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 lihzh31.* @alia OneCoder32.*/33.@Override34.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 lihzh43.* @alia OneCoder44.* @blog http://www.coderli.com45.*/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.@Override57.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 OneCoder71.* @author lihzh72.*/73.@Override74.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教程(三) 字串訊息收發