ChatServerHandler 服务器端控制类Handler,进行数据的处理
package com.xx.netty.server;
import java.net.InetAddress;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.GlobalEventExecutor;
/**
* 服务器端控制类Handler,进行数据的处理
* 2016年3月24日 下午3:33:07
* @author zhangxiaoping
*/
public class ChatServerHandler extends SimpleChannelInboundHandler {
static final ChannelGroup cg=new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
//接收客户端的输入
@Override
protected void channelRead0(ChannelHandlerContext arg0, String arg1) throws Exception {
for(Channel c:cg)
{
String[] msg=arg1.split("#");
if(c!=arg0.channel()){
//别人说的显示IP+ 说的话
c.writeAndFlush("["+msg[0]+"] "+ msg[1]+'\n');
}else {
//自己说的显示我+ 说的话
c.writeAndFlush("[我] "+msg[1]+'\n');
}
}
if(arg1.equalsIgnoreCase("bye"))
{
//说bye 关闭
arg0.close();
}
}
//连接服务器成功之后,服务器向客户端输出连接建立成功语句
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener(
new GenericFutureListener>() {
@Override
public void operationComplete(Future super Channel> arg0) throws Exception {
ctx.writeAndFlush("Welcome to "+ InetAddress.getLocalHost().getHostName()+"\n");
ctx.writeAndFlush("Your session is protected by "+ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite()+" cipher suite"+"\n");
cg.add(ctx.channel());
}
});
}
//异常处理
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
ChatServerInitializer 初始化服务器的相关配置
package com.xx.netty.server;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslContext;
/**
* 初始化服务器的相关配置
* 2016年3月24日 下午3:24:58
* @author zhangxiaoping
*/
public class ChatServerInitializer extends ChannelInitializer {
private final SslContext SslContext;
public ChatServerInitializer(SslContext sslContext) {
this.SslContext=sslContext;
}
@Override
protected void initChannel(SocketChannel arg0) throws Exception {
ChannelPipeline pipeline=arg0.pipeline();
pipeline.addLast(SslContext.newHandler(arg0.alloc()));
pipeline.addLast(new DelimiterBasedFrameDecoder(1024*8, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new ChatServerHandler());
}
}
ChatServer 服务器启动
package com.xx.netty.server;
import java.security.cert.CertificateException;
import javax.net.ssl.SSLException;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.SelfSignedCertificate;
/**
* 基于Netty框架的服务器端编写
* 2016年3月24日 上午10:04:13
* @author zhangxiaoping
*/
public class ChatServer {
//设置服务器端口
private static final int PORT=Integer.parseInt(System.getProperty("port","8800"));
//启动服务
public static void main(String[] args) {
EventLoopGroup bossGroup=null;
EventLoopGroup workerGroup=null;
try {
SelfSignedCertificate ssc=new SelfSignedCertificate();
SslContext sslContext=SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
bossGroup=new NioEventLoopGroup(1);
workerGroup=new NioEventLoopGroup();
ServerBootstrap bootstrap=new ServerBootstrap();
//建立连接
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChatServerInitializer(sslContext));
bootstrap.bind(PORT).sync().channel().closeFuture().sync();
} catch (CertificateException e) {
e.printStackTrace();
} catch (SSLException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放资源
if(bossGroup!=null)
bossGroup.shutdownGracefully();
if(workerGroup!=null)
workerGroup.shutdownGracefully();
}
}
}
ChatClientHandler 客户端处理类
package com.xx.netty.client;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* 客户端接收服务器处理好的数据,将其显示在窗体里面
* 2016年3月24日 下午4:13:25
* @author zhangxiaoping
*/
public class ChatClientHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext arg0, String arg1) throws Exception {
ChatClient.cList.add(arg1,0);
System.out.println(arg1+" ");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
ChatClientInitializer 初始化客户端相关配置
package com.xx.netty.client;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslContext;
/**
* 初始化客户端相关配置
* 2016年3月24日 下午4:01:48
* @author zhangxiaoping
*/
public class ChatClientInitializer extends ChannelInitializer {
private final SslContext sslcontext;
public ChatClientInitializer(SslContext sslContext) {
this.sslcontext=sslContext;
}
@Override
protected void initChannel(SocketChannel arg0) throws Exception {
ChannelPipeline pipeline=arg0.pipeline();
pipeline.addLast(sslcontext.newHandler(arg0.alloc(),ChatClient.HOST,ChatClient.PORT));
pipeline.addLast(new DelimiterBasedFrameDecoder(1024*8,Delimiters.lineDelimiter()));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
pipeline.addLast(new ChatClientHandler());
}
}
ChatClient 客户端 初始化客户端窗口发送数据等
package com.xx.netty.client;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.List;
import java.awt.Panel;
/**
* 客户端窗体编写
* 2016年3月24日 下午4:16:17
* @author zhangxiaoping
*/
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.net.ssl.SSLException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
public class ChatClient {
//定义全局变量
static final String HOST=System.getProperty("host","localhost");
static final Integer PORT=Integer.parseInt(System.getProperty("port", "8800"));
static List cList=new List(6);
TextField tfMsg=new TextField(7);
TextField tfData=new TextField(28);
static Channel channel=null;
static EventLoopGroup clientGroup=null;
static JTextField field=new JTextField(15);
static JButton logBtn=new JButton("登录");
static String username=null;
//初始化登录窗口
public ChatClient()
{
final JFrame logFrame=new JFrame("登录-xx-聊天室");
JPanel button=new JPanel();
button.add(new JLabel("姓名:"));
button.add(field);
button.add(logBtn);
logFrame.add(button,BorderLayout.SOUTH);
logFrame.setLocationRelativeTo(null);
logFrame.pack();
logFrame.show();
logFrame.setVisible(true);
logFrame.setResizable(false);
logFrame.setDefaultCloseOperation(logFrame.DISPOSE_ON_CLOSE);
//添加点击button的监听事件
logBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(field.getText().trim().toString().equals(""))
{
JOptionPane.showMessageDialog(null,"请输入姓名");
}else
{
username=field.getText().trim().toString();
System.out.println(username);
initFrame();
logFrame.dispose();
}
}
});
//添加点击关闭按钮的监听事件
logFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
clientGroup.shutdownGracefully();
System.exit(0);
}
});
}
/**
* 初始化聊天主窗体
* 下午7:58:05
*/
void initFrame()
{
final Frame cFrame=new Frame("欢迎"+username+"来到xx聊天室");
cFrame.setSize(300, 400);
cFrame.setVisible(true);
cFrame.setLocationRelativeTo(null);
cFrame.setResizable(false);
cFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
clientGroup.shutdownGracefully();
cFrame.dispose();
System.exit(0);
}
});
tfMsg.setText("输入信息:");
cFrame.add(cList, "Center");
Panel panel=new Panel();
panel.setLayout(new BorderLayout());
panel.add(tfMsg, "West");
panel.add(tfData, "East");
cFrame.add(panel, "South");
//输入框添加监听事件
tfData.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
if(!tfData.getText().trim().toString().equals(""))
{
String info=username+"#"+tfData.getText();
ChannelFuture cFuture=null;
cFuture=channel.writeAndFlush(info+"\r\n");
if(cFuture!=null)
{
cFuture.sync();
}
tfData.setText("");
}
} catch (Exception e2) {
// TODO: handle exception
}finally {
}
}
});
}
//初始化对象,建立客户端服务器连接
public static void main(String[] args) {
try {
final SslContext sslContext=SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
clientGroup=new NioEventLoopGroup();
Bootstrap bootstrap=new Bootstrap();
bootstrap.group(clientGroup).channel(NioSocketChannel.class).handler(new ChatClientInitializer(sslContext));
channel=bootstrap.connect(HOST,PORT).sync().channel();
new ChatClient();
} catch (SSLException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}