Netty学习4-Netty客户端基本结构

一、介绍

上一篇我们介绍了通过Telnet的形式连接Netty的服务端,实际上Netty也提供了客户端的相应功能,可以如果有了Netty客户端的配合,Netty的优势才能发挥的淋漓尽致。

二、启动Netty客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.sohu.tv.netty.train.client.main;
import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import com.sohu.tv.netty.train.client.handler.ClientHiHandler;
/**
* netty客户端
*
* @author leifu
* @Date 2016-5-29
* @Time 下午4:13:42
*/
public class NettyClientMain {
private final static String IP = "127.0.0.1";
private final static int PORT = 8888;
public static void main(String[] args) {
// 客户端
ClientBootstrap bootstrap = new ClientBootstrap();
// 线程池
ExecutorService boss = Executors.newCachedThreadPool();
ExecutorService worker = Executors.newCachedThreadPool();
// socket工厂
bootstrap.setFactory(new NioClientSocketChannelFactory(boss, worker));
// 管道工厂
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("hiHandler", new ClientHiHandler());
return pipeline;
}
});
// 连接Netty服务端
ChannelFuture connect = bootstrap.connect(new InetSocketAddress(IP, PORT));
Channel channel = connect.getChannel();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入");
channel.write(scanner.next());
}
}
}

nettyClient的初始化和nettyServer非常的像,只不过所有的Server都变为了Client。
一切准备就绪后,就开始用bootstrap连接NettyServer,并用channel发送数据。

三、Handler:处理服务端返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.sohu.tv.netty.train.client.handler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
/**
* 客户端handler
* @author leifu
* @Date 2016-5-29
* @Time 上午10:20:23
*/
public class ClientHiHandler extends SimpleChannelHandler {
/**
* 接收消息
*/
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("messageReceived");
String s = (String) e.getMessage();
System.out.println("string message is " + s);
super.messageReceived(ctx, e);
}
/**
* 捕获异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println("exceptionCaught");
super.exceptionCaught(ctx, e);
}
/**
* 新建连接
*/
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelConnected");
super.channelConnected(ctx, e);
}
/**
* 连接必须是已经建立的,关闭通道的时候才会触发
*/
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelDisconnected");
super.channelDisconnected(ctx, e);
}
/**
* channel关闭的时候触发
*/
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelClosed");
super.channelClosed(ctx, e);
}
}

和上一节介绍NettyServer时候是一样的。

四、问题

1.channelDisconnected与channelClosed的区别?

channelDisconnected只有在连接建立后断开才会调用。
channelClosed无论连接是否成功都会调用关闭资源。