了解了Netty的基本概念,开发起来应该会顺手很多。 在“Hello World”代码中,我们只是在完成绑定的时候,在各自的本地打印了简单的信息,并没有客户端和服务端的消息传递。这个肯定是最基本的功能。在上代码之前,先补充一个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。明确了这一点,接下来我们上代码:
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后,解码成字符串打印出来。