Java NIO框架Netty教程(三) 字符串消息收發
了解了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源碼中,是這樣判斷的:
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教程(三) 字符串消息收發