Netty实现带UI客户端服务器聊天功能
2016-03-02 21:54
483 查看
最近有点闲,用Netty这个异步框架写了个聊天功能,也算是对Java语言的一个回顾:
现有的例子总是使用回调去处理读写,但有时候我们确需要接受来自外界的输入,比如UI界面的消息输入,此时我们就需要提取Channel或者ChannelHandlerContext来进行消息的传输。
Client端的代码比较简单,提取Connect后的Channel直接进行write就可以写入消息:
public class NettyClient {
private String clientName = "beyondwu";
public static final int BUFFER_SIZE = 1024;
public static final int HISTORY_LIST_SIZE = 30;
private Bootstrap bootstrap;
private ChannelPipeline chanPipeline;
private Channel socketChannel;
private ClientMessageHandler msgHandler;
private List<String> historyMessage;
private List<ClientObserver> observerList;
public NettyClient() {
historyMessage = new ArrayList<String>();
observerList = new ArrayList<ClientObserver>();
}
public void clientInit() {
EventLoopGroup group;
// Configure the client.
group = new NioEventLoopGroup();
msgHandler = new ClientMessageHandler(this);
try {
bootstrap = new Bootstrap();
// msgHandler = new ClientMessageHandler();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
chanPipeline = socketChannel.pipeline();
chanPipeline.addLast(msgHandler);
}
});
// socketChannel = bootstrap.connect(serverIP, serverPort).sync().channel();
} catch (Exception e1) {
e1.printStackTrace();
}
}
public String getMessages() {
String messages;
Iterator<String> iter = historyMessage.iterator();
messages = "";
while (iter.hasNext()) {
messages += iter.next();
messages += "\r\n";
}
return messages;
}
public int connServer(String IP, Integer port) {
// Start the client.
ChannelFuture chanFuture;
try {
chanFuture = bootstrap.connect(IP, port).sync();
socketChannel = chanFuture.channel();
// Wait until the connection is closed.
System.out.println("connect");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}
public void sendMsg(String msg) {
String newMessage;
//Send to Server
ByteBuf sendMsg = Unpooled.buffer(BUFFER_SIZE);
sendMsg.writeBytes(msg.getBytes());
System.out.println("Going to Send: " + msg);
socketChannel.writeAndFlush(sendMsg);
newMessage = clientName + ": " + msg;
updateMsg(newMessage);
}
public void updateMsg(String msg) {
if (historyMessage.size() > HISTORY_LIST_SIZE)
historyMessage.remove(0);
historyMessage.add(msg);
notifyObserver();
}
public void register(ClientObserver observer) {
observerList.add(observer);
}
public void notifyObserver() {
Iterator<ClientObserver> iter = observerList.iterator();
while (iter.hasNext()) {
iter.next().update();//获得各Observer
}
}
} 对于服务器端,由于需要对连接进行监听,所以特定开了两个线程,一个线程负责连接,一个负责数据的读写,这样保证消息不会阻塞。另外采用了BlockingQueue进行消息的阻塞读取,这样等待来自UI的数据传输。
界面如下:
有些细节就没有更多的时间去考虑了,主要为了练习其中的部分api的使用。更多代码请访问我的github:https://github.com/wcwu/NettyChat
现有的例子总是使用回调去处理读写,但有时候我们确需要接受来自外界的输入,比如UI界面的消息输入,此时我们就需要提取Channel或者ChannelHandlerContext来进行消息的传输。
Client端的代码比较简单,提取Connect后的Channel直接进行write就可以写入消息:
public class NettyClient {
private String clientName = "beyondwu";
public static final int BUFFER_SIZE = 1024;
public static final int HISTORY_LIST_SIZE = 30;
private Bootstrap bootstrap;
private ChannelPipeline chanPipeline;
private Channel socketChannel;
private ClientMessageHandler msgHandler;
private List<String> historyMessage;
private List<ClientObserver> observerList;
public NettyClient() {
historyMessage = new ArrayList<String>();
observerList = new ArrayList<ClientObserver>();
}
public void clientInit() {
EventLoopGroup group;
// Configure the client.
group = new NioEventLoopGroup();
msgHandler = new ClientMessageHandler(this);
try {
bootstrap = new Bootstrap();
// msgHandler = new ClientMessageHandler();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
chanPipeline = socketChannel.pipeline();
chanPipeline.addLast(msgHandler);
}
});
// socketChannel = bootstrap.connect(serverIP, serverPort).sync().channel();
} catch (Exception e1) {
e1.printStackTrace();
}
}
public String getMessages() {
String messages;
Iterator<String> iter = historyMessage.iterator();
messages = "";
while (iter.hasNext()) {
messages += iter.next();
messages += "\r\n";
}
return messages;
}
public int connServer(String IP, Integer port) {
// Start the client.
ChannelFuture chanFuture;
try {
chanFuture = bootstrap.connect(IP, port).sync();
socketChannel = chanFuture.channel();
// Wait until the connection is closed.
System.out.println("connect");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}
public void sendMsg(String msg) {
String newMessage;
//Send to Server
ByteBuf sendMsg = Unpooled.buffer(BUFFER_SIZE);
sendMsg.writeBytes(msg.getBytes());
System.out.println("Going to Send: " + msg);
socketChannel.writeAndFlush(sendMsg);
newMessage = clientName + ": " + msg;
updateMsg(newMessage);
}
public void updateMsg(String msg) {
if (historyMessage.size() > HISTORY_LIST_SIZE)
historyMessage.remove(0);
historyMessage.add(msg);
notifyObserver();
}
public void register(ClientObserver observer) {
observerList.add(observer);
}
public void notifyObserver() {
Iterator<ClientObserver> iter = observerList.iterator();
while (iter.hasNext()) {
iter.next().update();//获得各Observer
}
}
} 对于服务器端,由于需要对连接进行监听,所以特定开了两个线程,一个线程负责连接,一个负责数据的读写,这样保证消息不会阻塞。另外采用了BlockingQueue进行消息的阻塞读取,这样等待来自UI的数据传输。
class BindThread extends Thread { NettyServer ntyServer; public BindThread(NettyServer server) { this.ntyServer = server; } public void run() { try { ntyServer.serverInit(); } catch (SSLException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } } } public class MessageWritenThread implements Runnable, ServerObserver { ServerUI frontServer; NettyServer nettyServer; public MessageWritenThread(ServerUI server) { frontServer = server; nettyServer = new NettyServer(); nettyServer.registerObserver(this); new BindThread(nettyServer).start(); //new Thread(this).start(); } @Override public void run() { //nettyServer.serverInit(); while (true) { String sendMsg = ""; try { System.out.println("now send msg: " + sendMsg); sendMsg = frontServer.getSendBuffer().take(); System.out.println("after now send msg: " + sendMsg); nettyServer.sendMsg(sendMsg); } catch (InterruptedException e) { e.printStackTrace(); } //nettyServer.(sendMsg); } } @Override public void update() {//can delegate frontServer.getContentArea().setText(nettyServer.getMessages()); } }
界面如下:
有些细节就没有更多的时间去考虑了,主要为了练习其中的部分api的使用。更多代码请访问我的github:https://github.com/wcwu/NettyChat
相关文章推荐
- 导入opencv.highgui.Highgui会报错
- ui-router详解(二)ngRoute工具区别
- c3p0 配置连接MySQL异常: java.sql.SQLException: Connections could not be acquired from the underlying datab
- POJ 3368 Frequent Values(RMQ)
- UITableview性能优化方案 iOS
- UVA 11995(p186)----I Can Guess the Data Structure!
- Handler消息传递机制(二)Handler,Loop,Message,MessageQueue的工作原理
- 线程
- hdu 3732 Ahui Writes Word 【多重背包】、好题
- ui-router路由控制器(一)
- css之marquee,让你的文字跳起来
- JSP 的 page 编译指令的属性session 的默认值 true
- [绍棠] iOS 在一个UILabel显示不同的字体和颜色
- poj2478 Farey Sequence 欧拉函数性质的简单应用
- question_010-JAVA之Set之HashSet的子类LinkedHashSet
- some frequently-used formula
- Builder模式
- Easyui---模态对话框实现ESC键一键锁屏(输入密码解锁)
- hdu Rescue (bfs)
- UI-进程与线程(多线程、主次线程)